JAMIE
A persistent AI development partner built on agent harnessing and context engineering.
[ read case study ]A design-system pipeline that turns one config source into a Figma library and a React catalog, kept in lockstep.
// Every atom on this page came out of it
Every time I started a new project the right way — modular UI, proper tokens, real components, dark mode, Figma parity — I spent the first few weeks on foundation work and never made it to the product.
The foundation kept eating the project.
Design and dev had to be set up twice: once in Figma, once in code, with manual translation between them. Every change meant updating both worlds and praying they didn't drift. A primary color tweak became a half-day of synchronization. I wanted to solve it once — a system where the design tokens, the Figma library, and the production code all came out of the same source.
That's Loom.
One config source, two codegen pipelines, a catalog you pick from. Five pieces, start to finish.
One file you write by hand — spec/answers.json: brand colors, font pairing, spacing density, edge style, the type scale. About a dozen decisions, answerable in one sitting. It compiles to the base token configs in the spec/config/ directory, and everything downstream reads from those. Change an input, regenerate — nothing else gets hand-edited.
The same config feeds two codegen pipelines. assemble-figma.js builds the Figma file — variables, text styles, components. orchestrator.js builds the React catalog. Both read the identical JSON, so a brand color or a component spec is defined once and lands in both worlds.
The catalog spans eight groups — buttons, forms, layout, feedback, data display, navigation, composite, motion. Each atom is a .tsx component plus a .manifest.json declaring its dependencies, variants, and tokens. Visual treatment and color are orthogonal CVA (class-variance-authority) axes — filled / outline / ghost × brand / severity — so adding either is one line, not an N×M matrix. The four motion atoms are zero-dependency — hand-rolled on IntersectionObserver and requestAnimationFrame, no animation library.
You don't install the whole catalog. A loom-picks.json in your project lists the atoms you want; setup.shreads it, resolves each pick's dependencies transitively from the manifests — pick combobox and it pulls in popover and form-field— and copies just that subset into your project. After that the files are yours. It's the shadcn model: own the copies, no upstream dependency.
init.sh bootstraps the app shell once — ThemeProvider, root layout and fonts, the token substrate. setup.sh syncs the picked atoms and re-runs whenever the picks change. It prints the npm install line for whatever those atoms import rather than installing anything itself — your project owns its lockfile.
One config source, two synchronized worlds. spec/answers.json compiles to the base token configs. The Figma pipeline reads them; the code pipeline reads them. Change a token, regenerate, both worlds update — Figma and code in lockstep. The cost is discipline: every change has to flow through the generator, so a new feature ships to both layers or neither. The payoff is that drift can't happen structurally, not just discouraged. There is no second source to drift from.
Open source, the shadcn way. Loom started as a private engine for my own projects. Going open in v2 was deliberate: the reusable part isn't my brand, it's the model — one source feeding two pipelines, a catalog you copy from instead of depend on. So it's public on GitHub under an MIT license, and consumption is shadcn-style: you pick atoms in loom-picks.json and own the copies — no npm installstep, no upstream sync. The cost is real: a fix to a catalog atom doesn't auto-propagate to projects that already picked it, and multi-project consistency takes deliberate re-picking. The payoff is zero lock-in — the atoms are yours the moment they land, with no version treadmill to stay on. Validated in production across multiple downstream products.
Paste-go Figma scripts, not a Figma plugin. The Figma side is thirty scripts pasted into the Plugin API console, not a packaged plugin. The payoff is portability and granularity: no plugin to install per account, no runtime, no permissions — and because each component script clears and rebuilds its own page on re-paste, you can update one family in isolation, re-running just the buttons script to change the buttons with siblings untouched. The cost is no GUI — a full build is the shared-utils helper plus the step scripts pasted in order, and the token/variable steps aren't idempotent, so rebuilding thoseonto an already-populated file means clearing it first. The whole "front end" stays plain text you can read and diff.
JSON in, files out. The four slices below show the shape of the pipeline end to end — pick one.
The single source of truth. The questionnaire compiles to five JSON files — this is colors.json, the palette and role mapping every downstream step reads from.
{
"$note": "Generated from primary: #1E90FF, secondary: #1E90FF, accent: #1E90FF.
Neutral tinted from primary hue (210°). Questionnaire is the override
mechanism — change inputs and regenerate.",
"palette": {
"primary": { "50": "#ecf2f9", "300": "#4da7ff", "500": "#006dd6", ... },
"secondary": { ... },
"neutral": { "5": "#0c0d0e", "15": "#242629", "90": "#e4e6e7", ... },
"success": { ... },
"warning": { ... },
"error": { ... },
"info": { ... }
},
"roles": {
"dark": { "surface": "neutral.10", "on-surface": "neutral.90", ... },
"light": { "surface": "neutral.95", "on-surface": "neutral.10", ... }
}
}A persistent AI development partner built on agent harnessing and context engineering.
[ read case study ]A digital bulletin board for spontaneous event planning — events are posters, your people and calendars are the boards.
[ read case study ]