Design System + Engineering
A Claude Code control plane that turns creative direction into dev-ready Figma frames, bound to the design system, consumable in Dev Mode, with zero spec drift.
Design and dev drift the moment the handoff ends
A design system promises one source of truth. The truth splits the second a frame leaves Figma: detached instances, hardcoded hex, placeholder copy, components that won't resolve in Dev Mode. Most teams fight this with review, catching the drift after it happens.
I wanted the other approach: make drift structurally impossible. Hand creative direction to an agent that can only build with the real components and the real tokens, so the frames arrive dev-ready by construction, not by review.
Separate the control plane from the artifacts
The artifacts (frames, components, variables) stay in Figma. That's already the source of truth, so I don't duplicate it. The control plane is a small git repo that drives the agent: the operating contract, a local mirror of the tokens, a component index, the design rules, and the skills that load them. No design source files ever live there.
Its only job is to make the agent produce correct Figma output every time, on the smallest possible context budget. Everything else serves that.
A control plane that retargets by folder swap
I built it around the Unify DS, but the core is system-agnostic. A generic layer holds the durable contract and the design knowledge; a single ds/ folder holds everything specific, the tokens, the component manifest, the product context, the rules. Point it at another system and the whole workflow follows.
Operating contract
A durable PLAYBOOK plus a /design skill that loads the DS rules and HCI laws before a single frame is drawn.
Token mirror + resolver
JSON mirrors of every Figma variable, read through one resolver call per lookup. Raw token files never enter context.
Component manifest
A lookup index of library components, variants, and keys, so the agent reaches for the real instance, never a copy.
Swappable ds/ folder
The generic core stays put; ds/ is the only thing that changes per system. Retarget by folder swap, not a rebuild.
Where the templating boundary lives
The split is the whole trick. Root-level files (the PLAYBOOK, principles/, templates/) survive any design system. The ds/ folder is the only thing that changes when I retarget. Drop a different ds/ in and the workflow points at a new system.
/
├── PLAYBOOK.md # durable operating contract (DS-agnostic)
├── .claude/skills/
│ ├── design/ # /design — loads rules before any frame
│ └── design-critic/ # /design-critic — the self-review loop
├── ds/ # THE SWAP POINT — everything DS-specific
│ ├── config.md # Figma file URLs, domain, defaults
│ ├── product-context.md # product, personas, sample data (kills lorem ipsum)
│ ├── design-rules.md # strict, numeric rules (override the PLAYBOOK)
│ ├── components.md # component manifest (a lookup index, not a copy)
│ ├── icons.md # flat list of icon names
│ ├── figma-keys.md # captured library / variant / text-style keys
│ └── tokens/ # JSON mirrors of Figma variables
│ ├── colors.json · semantic.json · spacing.json · radius.json
│ └── _resolver.sh # single entry point for ANY token lookup
├── principles/ # DS-agnostic knowledge
│ ├── hci-laws.md # UX/HCI laws for design + critique
│ ├── design-anti-patterns.md # real mistakes + the rule that prevents each
│ └── figma-plugin-api.md # operational notes for writing to Figma
└── templates/
└── brief.md # the format designers and PMs hand you
Brief in chat, dev-ready frame out
A brief lands in chat: screenshots, component links, or a filled-out template. From there the workflow is deterministic, and it reviews itself before it ever asks for my time.
Read only what's needed
Token values from the resolver, component metadata from the manifest, geometry pulled from Figma only for the components the brief actually names. The agent probes the file once by key and caches what it learns.
Design in the canvas file
Frames auto-laid out, every value bound to a semantic token so light and dark hold automatically, every component a real instance. No detached copies, no hardcoded hex, no lorem ipsum.
Critique before handoff
After every build the agent runs a structured self-review against the reference, applies every priority fix, and only then surfaces the frame, with the screenshot, the node ID, and any open question.
Dev-ready by construction, not by review
The frame that reaches an engineer is already correct. Open it in Dev Mode and every token, variant, and component resolves: nothing detached, nothing hardcoded, no off-token spacing, no placeholder copy left to clean up. The review step that used to catch spec drift has nothing left to catch.
Autonomy, drawn as a line it can't cross
The agent brings taste only where the brief leaves room. Everything else defaults to asking, encoded so it never has to guess where the line is.
| Decision | Default |
|---|---|
| Color within a utility ramp | Proceed silently |
| Spacing or radius on the token scale | Proceed silently |
| Creating a local component | One-line flag in chat |
| Copy phrasing | Proceed, paste samples |
| Information architecture or flow | Ask first |
| A net-new pattern | Ask first |
| Departing a core component's intent | Ask first |
The design system and the brief always win over preference.
Honest tradeoffs
This isn't zero-setup. The first system takes real work: writing rules specific enough to be enforceable, curating the token exports until the resolver passes its tests, capturing the Figma keys. The payoff is that the second feature, and the hundredth, are nearly free, and every one lands dev-ready.
It also doesn't replace design judgment. It replaces the mechanical part, the binding, the spacing math, the variant-picking, the "did this detach" anxiety. The direction stays mine; the agent just makes sure it survives the trip into Figma intact.
“Stop reviewing for drift. Build so it can't drift.”
— Operating principle