A design system product managers can prototype with in Claude
Bibel TV has no in-house designers, so product managers and product owners shape new features. I made Storybook the shared reference, gave Claude a closed list of valid token names, and set up checks that refuse an off-system value and name the token to use instead.
An off-system value gets refused by name, before anyone has to spot it
- The setting
- Bibel TV, a German broadcaster moving from linear TV to apps and streaming. Product managers and product owners shape new features, with limited Figma skills.
- My part
- Head of Product Design, and the entire in-house design capability. I made Storybook the source of truth, gave Claude a closed token vocabulary to work from, and set up six checks that run locally and in CI.
- What changed
- A hardcoded value or an invented token used to compile and render like any other change. Now the checks refuse both and name what to use instead. Storybook, the vocabulary and the checks run today; the full path from a prototype to a pull request is what they are being built toward.
- Three takeaways
- Make the shared reference something a person can run. Give the assistant a closed list of valid names. Make a refusal say what to use, and warn when the match is only by value.
Two mistakes that compile and render
To show what the checks do, I staged a two-line change in a throwaway copy of the prototype repo. It gives a suggestion chip a corner radius written as a plain 16, and padding from a spacing token that doesn't exist.
Both compile and render. The 16 isn't even visible: the token it replaced is 16px in every theme and device mode, so the chip renders pixel-identical. Nothing on screen gives it away.
Catching exactly this, a value nobody decided in a change that looks finished, is why the checks exist.
The people shaping features are product managers
Bibel TV has no in-house designers or developers. Product managers and product owners shape new features, and they are the people now building with AI. I am the design function, singular.
So the design system has to be usable by people who did not build it, and the standard has to hold without a designer reviewing every screen. If AI writes more of your interface and nobody reads every screen, the same question is already on your desk.
Figma could not be the way in
The product managers' Figma skills are limited, and there is no meaningful way to upskill them into maintaining a component and token system in Figma.
Yet a prototype can need an existing component, a changed one, a new view, a new token or a new alias. Each of those is a design decision. Without a guided path, a prototype improvises it, and the improvised value looks just like a decided one.
Storybook became the source of truth, and the vocabulary became closed
So the source of truth moved out of Figma and into Storybook, where the components are real and runnable, reading from the token API. A new design language and a set of new components were landing, and the people who needed to build with them were product managers, not designers.
The intended path from prototype to pull request. The gate on it is live: six checks, locally and in CI.
Claude gets the same closed list a person would. An MCP server hands it the token vocabulary with a plain instruction: these are the only valid names, do not invent. The enumerated vocabulary that keeps the assistant on the compliant path is also what makes the system self-serve for a product manager.
Six checks, identical locally and in CI, refuse a token reference that doesn't resolve and a value written straight into a component. A token is a guideline until something enforces it.
A refusal names what to use instead
Run against the staged change, both checks fail. One names the invented spacing token as a reference that doesn't exist. The other refuses the hardcoded 16 and suggests three real radius tokens.
A change staged for this page, run against the real checks. The invented token is refused by name. The hardcoded 16 is refused with three real tokens to use instead, and a warning that matching the number doesn't make the binding right.
The second check also attaches a warning: the match is by value, so someone has to confirm the binding is semantically right. The output below is verbatim, apart from a shortened file path.
-
Stage the change
The example changes two lines: one component value becomes a literal 16, and one spacing reference points to a token that does not exist. Both still compile and render.
-
Run the same checks as CI
The phantom-reference check names the invented token. The literal-value check refuses the 16 and offers three real radius tokens that match its value.
-
Return the semantic choice to a person
A matching number is not proof of the right relationship, so the check warns that someone still has to confirm which token expresses the intended decision.
Twelve pixels is not twelve pixels
Claude made exactly this kind of error once. It gave a value the correct number, twelve pixels, and aliased it to the wrong primitive or semantic token. The pixels were right. The relationship was not.
Illustrative: a correct value, aliased to the wrong primitive or semantic token.
Two design decisions now shared a number by coincidence. Nothing looked wrong, and nothing would have, until a later change to the unrelated token moved this value with it, for no design reason.
Equal values don't prove that one decision should alias another. That is what the warning on every value match says.
What runs today, and what it is for
View full size ↗ Storybook, the shared reference: the real components, reading from the token API.
The same donation card in two states: frosted, and plain.
- The shared reference
- Figma, where the product managers' skills are limited Storybook, with the real components, reading from the token API
- Enforcement
- a plausible Claude result could invent a token or hardcode a value and still compile and render. Six checks, identical locally and in CI, refuse the unresolved reference and the hardcoded value
- Exceptions
- A value that genuinely isn't a design decision can pass, but only with a reason, and every exception is recorded instead of taken silently.
- Being built
- The full path from a product manager's prototype to a pull request against Storybook and the token API. The MCP prototyping server is in active development, and a colleague uses it to prototype his project.
The next hardcoded 16 stops at the check
The staged chip still looks exactly like the real one. What changed is the next step: the change stops, the invented token is named, and three real radius tokens are on the table.
Which one fits is a design decision. The check hands it back to a person, with the warning attached.
Guardrails worth copying into your own system
-
Make the shared reference something a person can run.
If your reference is a design file, everyone building from it has to translate it first. The test: can someone who didn't build the system find and use the right part without a guide?
-
Give the assistant a closed list of valid names.
Enumerate the vocabulary instead of trusting recall. Then a name outside the list becomes a refusal you can see, instead of a plausible invention.
-
Make a refusal say what to use, and warn when the match is only by value.
Plant a mistake yourself and run your checks against it. If the output names no fix, or offers a same-number token with no warning, a non-designer will take whatever it says.
A review loop may be cheaper where designers read every screen
Where designers review interface work before it ships, a review loop may be the cheaper mechanism, and this infrastructure more than you need.
The checks also need code to run against. They read the component code, so a static mockup gives them nothing to refuse.
Want to hear more?
- Write to me with the last value that slipped into your product without anyone deciding it, and where it was caught, if it was. I'll tell you which of these checks would have stopped it.