Design law an AI obeys
- Sole author of the rule system and the component library
- 4,058 lines of rules · 55 components · 363 stories
- In use
The problem, and what it became
Four designers, no shared source of truth, and a handoff gap that reopened on every screen. The usual answer is a component library — but a library only fixes the half of the problem where someone already knows which component to reach for.
What shipped is two things, and the second is the interesting one. There is a library: 55 components, 363 stories. And there is a specification — 4,058 lines across six files — that an AI is required to satisfy before it may write a single line of screen code.
I do not write production code. That turned out to matter less than expected, because the leverage was never in writing the components. It was in writing down the rules precisely enough that something else could build against them and be told, in specific terms, when it was wrong.

From Figma to Storybook
The migration itself was the easy half, and it is worth saying so plainly. Components move across reliably once the tokens do — the work is deciding what a token means, not what colour it is.
So the token layer is semantic all the way down, and primitives are prohibited rather than discouraged. text-text-level3 names a role in a hierarchy; text-gray-400 names a shade of grey and tells the next person nothing.
Text color → always text-text-*
text-text-level1 dark body text (default)
text-text-level3 helper / supporting text
text-text-on-brand fixed white on brand surfaces — NEVER inverts in dark mode
❌ Never: text-gray-900, text-gray-400, text-white
Border radius → always use design system radius tokens
rounded-500 pill / full-rounded (9999px)
rounded-100 card / modal (8px)
❌ Never: rounded-full, rounded-xl, rounded-lg
If a token is missing, flag it — don't invent a workaround.
The rule layer
Six files, each with a job. COMPONENT_MAP says which component serves which intent. PATTERNS holds eleven screen patterns and the density limits for each slot. LAYOUT fixes the four layout types and when each is allowed. UX_RULES covers grouping, hierarchy and cognitive load. AGENTS is the execution protocol. FEEDBACK_LOG records what changed and why.
The rules are written to be executed, not admired. That means they say what happens when they cannot be followed — which is the part most design documentation leaves out, and the part that decides whether a system survives contact with a real screen.
Four decisions
Each one in the same shape: what was true, what I chose, and what it cost.
Nothing is built until a human confirms the plan
- Given a screen request, an AI will produce a screen. It will be plausible, it will use real components, and any wrong assumption inside it is now buried in code that looks finished.
- A planning gate. Before any code, the intent, the layout type and the pattern must each be stated with one sentence of reasoning — and then it waits for explicit confirmation. This applies to every screen prompt regardless of how detailed the request is, and to edits as well as new work.
- A round trip before anything appears on screen, every single time, including for changes that turn out to be trivial. That is the price of the disagreement surfacing while it is still a sentence rather than a screen.
Before building any new screen, Claude MUST follow this sequence — no exceptions:
1. Identify the primary intent of the screen (COMPONENT_MAP.md)
2. Select the layout type (LAYOUT.md S10):
full-stretch · centered · aside-panel · proportional-split
3. Select the pattern that matches the primary intent (PATTERNS.md P1–P11)
4. State all three — intent, layout, and pattern — with one sentence of
reasoning for each. Wait for explicit user confirmation before
writing any code.
5. If no pattern fits, state that explicitly. Do not force-fit a pattern.Four validation outcomes, not two
- Pass/fail is too coarse to be honest. A rule can go unsatisfied because a higher-priority rule blocked it — that is not a failure, and calling it one teaches everyone to ignore failures.
- Four outcomes. PASS and FAIL do the obvious work. CONSTRAINED PASS means a higher-priority rule blocked this one, and it must name which rule and why. DENSITY FLAG means a slot has more content than its pattern allows.
- Two extra states that a reviewer has to understand before the output means anything. A binary result is easier to read and would have hidden exactly the cases worth reading.
The distinction that earns its keep is CONSTRAINED PASS. It is the system saying this is the best available answer, here is what stopped it being better, and you may change the rule that blocked it. A binary check would have recorded that as a pass and lost the reason.
A density flag stops the machine
- When there is more content than a layout can hold, the tempting behaviour is to render it anyway — smaller, tighter, scrolling. Every one of those is a silent UX decision made by a tool, on a question that belongs to a person.
- DENSITY FLAG halts generation outright. No output. It states which slot exceeded its threshold, the current count, the hard maximum, and the recommended alternative from PATTERNS.md — then waits. The human decides whether to cut content, accept the overflow, or raise the threshold.
- The system refuses to finish a job it could have finished badly. On a deadline that is genuinely annoying, and it is the whole point — a tool that degrades quietly is worse than one that stops loudly.
If any check = DENSITY FLAG:
→ Claude MUST NOT generate output
→ Claude MUST state: which slot exceeded its threshold, the current
count, the hard maximum, and the specific recommended alternative
from PATTERNS.md
→ Claude MUST wait for explicit user instruction before proceeding
→ The user decides whether to reduce content, accept the overflow,
or update the threshold in PATTERNS.mdRules are ranked, because rules contradict each other
- Any rule set large enough to be useful will eventually tell you two incompatible things. Left unranked, whichever rule was read last wins — and the system becomes unpredictable in exactly the situations it exists for.
- An explicit priority order: LAYOUT, then COMPONENT_MAP, then PATTERNS, then UX_RULES. Lower priority must not override higher. Conflicts within LAYOUT resolve through its own internal tiers, and any conflict that cannot resolve must be surfaced rather than absorbed.
- UX_RULES sits last, which means the layer closest to the user's experience is the one that yields first. I would rather that be written down and arguable than left to whichever file happened to be read most recently.
If rules conflict:
1. LAYOUT.md
2. COMPONENT_MAP.md
3. PATTERNS.md
4. UX_RULES.md
Lower priority rules MUST NOT override higher priority rules.
If conflicts arise, Claude MUST surface them instead of silently
degrading UX.How a designer actually uses it
The test of all of this is whether a designer who has not read 4,058 lines can get a compliant screen out of it. SCREENS.md is the onboarding doc for exactly that: describe the screen in a few lines, confirm the plan the system proposes, and the rules do the rest.
These three came out of that process. They are production screens for an ads product — not component demos — and each one is worth reading against the rules above.

The next one is the clearest evidence that the rules are load-bearing rather than decorative. LAYOUT restricts the proportional-split layout to creation and editing flows that need a real-time live preview — and this is one: targeting on the left, estimated reach and daily impressions updating on the right. The screen is shaped by a rule you can read on this page.


The components
The library underneath. Every component ships its variants as stories, which is what makes the rules checkable — a rule about button shape is only enforceable if every shape exists somewhere you can point at.



It is published, so it can be opened rather than described. The Storybook below is the live build — the same one the figures above were captured from.
What I'd watch
Rules rot faster than components. A component that drifts from the spec is visible the moment someone opens Storybook. A rule that has quietly become wrong is invisible, and it keeps being obeyed — which is worse than having no rule, because now something is enforcing it. FEEDBACK_LOG exists for that reason and is the file I would watch hardest.
And the priority order in decision D is a bet I would revisit. Putting UX_RULES last makes the system predictable, and it means the layer closest to the person using the screen is the first to give way. That is the right trade for consistency across a team. I am not certain it stays right as the number of screens grows, and the honest answer is that CONSTRAINED PASS was built so that question keeps getting asked out loud instead of settled once.