DEV Community

Cover image for Crucible v1.0 — generate React, Vue, and Angular components that you actually own
Naveen R
Naveen R

Posted on

Crucible v1.0 — generate React, Vue, and Angular components that you actually own

I shipped Crucible v1.0 today. It's a code generation engine — you run a CLI command, it writes production-ready component source files into your project, and then it disappears. Zero runtime footprint. You own every line.

npx crucible add Button
# writes Button/Button.tsx, Button/Button.module.css,
# Button/Button.types.ts, Button/README.md
# into your project. yours forever.
Enter fullscreen mode Exit fullscreen mode

I built it because I kept running into the ceiling of what component libraries let you do — and I wanted to see what the "no library, just code" model looked like taken further than copy-paste snippets.

Here's how it works.


The five-layer pipeline

crucible.config.json
  → Config Layer      read + validate with ajv
  → Token Resolver    CSS custom props + OKLCH dark mode derivation
  → Component Model   normalised IR for templates
  → Template Engine   Handlebars, strictly logic-free
  → File Writer       hash protection + Prettier formatting
Enter fullscreen mode Exit fullscreen mode

The IR (intermediate representation) layer is the decision I'm happiest with. Without it, templates become conditional nightmares — {{#if angular}}, {{#if dark}}, {{#if compoundComponents}}. With it, all that logic lives in TypeScript where it can be typed and tested. Templates become pure interpolation.

Templates are audited on every build. Comparisons, ternaries, and else-if chains are prohibited at the .hbs level. npm run audit:templates runs as a prebuild hook and fails the build on any violation.


Token resolution

Tokens deep-merge with your chosen preset. Set only what you want to change:

{
  "theme": "minimal",
  "tokens": {
    "color": { "primary": "#FF6B6B" }
  }
}
Enter fullscreen mode Exit fullscreen mode

Only primary changes. The rest of the minimal preset — radius, typography, backgrounds — is untouched.

Everything resolves to CSS custom properties. No mode ever hard-codes a hex value:

:root {
  --color-primary: #FF6B6B;
  --radius-md: 8px;
  --spacing-unit: 4px;
}
Enter fullscreen mode Exit fullscreen mode

OKLCH dark mode

Dark tokens are derived in OKLCH, not HSL.

HSL lightness shifts change perceived hue — blue can drift toward cyan, purple toward gray-purple. OKLCH is perceptually uniform: lightness changes without hue drift.

{ "darkMode": { "strategy": "auto" } }
Enter fullscreen mode Exit fullscreen mode

That's the whole config. Crucible derives the full dark palette automatically and emits it as [data-theme="dark"] CSS vars alongside the light :root block.

Manual override is also supported for specific tokens.


Framework output

Three frameworks, three style systems — parallel template folders, no {{#if framework}} anywhere in the templates themselves:

Framework Patterns used
React 18+ Hooks, CSS Modules, compound components (static property pattern)
Vue 3.4+ Composition API, <script setup>, named slots
Angular 17+ Standalone components, @if/@for, ng-content

Style systems: css (CSS Modules), scss (SCSS Modules), tailwind (Tailwind v4 with CSS variable arbitrary values).

Adding a new framework means adding a template folder — nothing in the engine changes.


Hash-based overwrite protection

Every generated file gets a content hash stored in .crucible/manifest.json. On re-generation:

  • Hash matches → overwrite (file is unchanged from generated output)
  • Hash differs → warn and skip (you've edited it; Crucible leaves it alone)
  • --force → overwrite regardless
  • --dry-run → print what would happen, write nothing

The manifest key includes the component subfolder name (Button/Button.tsx) to prevent collisions across components.


CLI

crucible init              # scaffold crucible.config.json
crucible add Button        # generate one component
crucible add -a            # generate all components
crucible add Button --stories  # with Storybook stories
crucible eject             # copy preset tokens into config for full manual control
crucible tokens            # regenerate tokens.css only
crucible doctor            # check Node version, config validity, framework install
crucible config            # print resolved config
crucible clean             # remove generated files
Enter fullscreen mode Exit fullscreen mode

All commands have short aliases: a, i, d, t, e, l, c, cfg.


Components in v1.0

Button · Input · Card · Dialog · Select

Each one: full variant/size/state matrix, TypeScript types, compound components (React) / named slots (Vue) / ng-content (Angular), WCAG 2.1 AA accessibility, auto-generated README.


Test coverage

230 unit tests, 24 test files, 19 E2E phases.

E2E phases cover every framework × style-system combination (React/Vue/Angular × CSS/SCSS/Tailwind = 9 phases), plus write protection scenarios, batch generation, theme presets, custom output directories, and all CLI commands. Each phase runs in an isolated temp directory.


Repo

github.com/Naveen2070/project_crucible — MIT, open from day one.

Good first contributions: Textarea, Badge, Checkbox. The pattern is: add to src/registry/manifests/defaults.ts, create template files in the right framework folders, run the test suite. The engine discovers new components automatically.

Happy to go deep on any of the architecture decisions in the comments.

Top comments (0)