Most design systems live in Figma. A coding agent has not seen Figma; it sees files. So when you ask Claude Code, Cursor or Lovable to build a new screen, the agent writes #6b7280 where you meant "muted text", picks rounded-lg where each card on the site is square, and adds a hover lift to a block that is not a link. Nothing is broken, and the product drifts a little with each screen.
I build this site with Claude Code, and I stopped the drift by moving the design system into the place the agent looks: a few files next to the code, written for a reader who has no eyes.
What an agent needs from a design system
Four things. The rest is nice to have.
One way to colour. Semantic tokens with role names, and a rule that says they are the only way. text-foreground, bg-card, border-border, text-muted-foreground. Not gray-500. A raw colour name tells the agent what the colour is. A role tells it when to use the colour, and the role maps to both themes on its own.
Rules in a file it reads before it works. Not a wiki or a Figma page. A markdown file at the root of the repo, short enough to be read whole on each task.
A list of what exists. The components, one line each: what it is, when to use it, when not to. An agent that knows what exists reuses it. An agent that does not builds a second version.
A check that runs after each edit. The agent will slip. A small script that reminds it of the rules the moment it touches a component catches most slips before they land.
How this site does it
The whole system is three files and a hook.
The rules: CLAUDE.md
Claude Code reads CLAUDE.md at the start of each session. The design part of mine is under a hundred lines, and the first six rules do most of the work:
- Semantic tokens only for colour, never a functional colour by hand. The two exceptions are named: brand logos and on-page demo content.
- Both themes, always. A new token gets a value in
:rootand in.dark, in the same commit. - Reuse the catalog before adding a component.
- Stick to the scales. Type, spacing, radius, widths. A step on the scale, or a reason in the commit.
- Square corners, round controls. Cards, media and panels are square. Buttons, chips, nav pills and avatars are circles. No other radius.
- Keep the catalog in sync. Rename a token or add a component, update the reference file.
None of these is taste. "Make it feel premium" tells an agent nothing. "The radius for surfaces is zero" is a rule it can follow and a script can check.
The reference: DESIGN_SYSTEM.md
The long file. The token table, with each token's role in one sentence. The type scale, six steps, with the use of each. The content widths, four of them, named. The component catalog: one entry per component, what it takes, where it is used, and the decisions behind it, with dates. When a rule changed, the entry says when and why.
The agent reads the part the task touches, because the file is organised by what you would be touching. The catalog gets read most. Half of "build me a card for X" is answered by "we have FeedCard, it takes these props, use it".
The tokens: globals.css
Tailwind v4 with the tokens defined once in CSS, :root for the light theme and .dark for the dark one, mapped to utilities through @theme inline. Cut down:
:root {
--background: oklch(0.988 0 0);
--foreground: oklch(0.145 0 0);
--muted: oklch(0.97 0 0);
--muted-foreground: oklch(0.25 0 0);
--border: oklch(0.922 0 0);
--radius: 0;
}
.dark {
--background: oklch(0.145 0.006 65);
--foreground: oklch(0.87 0.006 65);
/* ... the same names, the night values */
}
The agent writes text-muted-foreground, and both themes come along. The radius token is zero, so rounded-xl on a card draws nothing, and the square-corner rule holds even where an old class slipped through.
The check: a hook
Claude Code can run a script after each file edit. Mine is twenty lines. When the edited file is a component, the token file or a data file, it puts a short note back into the agent's context: colour from tokens only, both themes, update the reference if you added anything. It does not block the edit. It makes the rule visible at the moment the agent is about to break it, which is when the agent is most likely to follow it.
Together these four do something a Figma library cannot. The design system is the running code, and there is no handoff. The agent builds the next component from the same tokens and the same rules the last one was built from, and the result comes out on-brand without me checking each line. That is the "systems that extend themselves" part of how I work.
What goes wrong
The rules are too long. An agent skims a two-thousand-line file the way a person does. Keep the rules under a hundred lines and put the detail in the reference file it can search.
The rules are in the wrong place. A docs/design.md that nothing points to goes unread. The root file gets read. If your tool reads one file by convention, that is the file.
Tokens with raw names. blue-500 is a palette. The agent needs the role. If the token is called accent, the agent uses it for the accent. If it is called blue-500, the agent uses it anywhere blue would look fine, which is most places.
No "never" list. Agents follow prohibitions better than preferences. "Prefer semantic tokens" produces hex codes within a week. "Never hardcode a functional colour" holds.
No example of the right thing. A rule plus one component that follows it is worth ten rules. Point the agent at the component you are happiest with and say "like this one".
The catalog goes stale. The day you add a component without an entry is the day the agent builds a duplicate. People drop the sync rule first, and the hook exists mostly to stop that.
Start with thirty minutes
You do not need the whole thing on day one.
- Write ten tokens in your CSS: background, foreground, muted, muted foreground, border, accent, and the dark values for each.
- Write five rules in the file your tool reads: tokens only, both themes, reuse first, one spacing scale, one radius rule.
- List the components you already have, one line each.
- Ask the agent to build one small component.
- Read what it got wrong. Each mistake is a missing rule. Add the rule instead of the fix.
Repeat steps four and five a few times. After a week the agent gets it right more often than the last freelancer did, because the freelancer had the Figma file and the agent has the rules.
If your system lives in Figma, how does code get built from it today? If the answer is "someone looks at the file", that someone is the system, and they do not scale.
