Unlisted case study

Agentic design systems

I built three design systems in ten weeks: a client rebuild in three and a half days, a public registry, and my own kit. This is the working method that made that possible, and what I now believe about where a designer’s judgment should live.

Design systemsAgentic workflowDesign opsBenchmarkingAccessibility

A design system used to be a library plus a PDF of good intentions. Working with AI agents changes the economics: the library gets cheap, and the intentions become the expensive, load-bearing part. An agent will happily produce the ninetieth component; whether it is the right component, on the right tokens, with its states proven, depends entirely on where the rules live and whether anything enforces them.

Between June and August 2026 I ran that thesis through three systems of very different shapes: a component library rebuilt inside a client engagement, an open-source registry of AI-product components, and the minimal kit I use for my own work. Same method each time, harder each time. Every number below comes from a repo, a CI run, or a git log.

Year
2026
Role
Designer, directing agents
Type
Working method, across three systems
Scale
94 + 116 + 97 components, ten weeks
Proof
Gates in CI, hooks at write time, measured audits
Stack
React 19, TypeScript, Tailwind v4, Storybook, Claude
Client engagement
Client rebuild
94 components, 3.5 days

152 commits, 24 merged PRs, benchmarked against a peer library on day three.

Public registry
Super AI Components
130 installable items

The registry with the deepest guardrail stack: gates, hooks, and agent waves.

Personal kit
Minimal Design System
97 components

Three-tier tokens, a capability contract, and debt that is only allowed to shrink.

unslop audit
client rebuildregistrypersonal kitthis site

An anti-slop taxonomy born under client deadline pressure, now a skill in four repos.

token gate
registrypersonal kitthis site

A script that fails the build on raw values. Each repo carries its own rules.

write-time guard
personal kitevery repo on my machine

One global hook runs whichever repo's gate is nearest. Repos without one are untouched.

case stories
theoryregistryclient rebuild

Named proof-states for components. Piloted, it caught a shipped contrast bug in an afternoon.

Three systems, and the guardrails that moved between them instead of being rebuilt. Every arrow is a documented port: the receiving repo cites the origin in its own files.

Three and a half days, then a benchmark

The client engagement is the stress test of the method, so it stays anonymous here: no names, no screens, method only. The shape of it: 94 components, 152 commits, 24 merged pull requests in about three and a half days, with agents implementing against specs while I made the calls a system actually depends on. Which primitives exist. What the token contract is. What done means.

On day three I benchmarked the result against a colleague’s parallel library for the same product. Their side: 40 components with roughly fifteen stories each. Mine: 94 components with roughly three. One number per library would have declared a winner and taught nothing, so the benchmark stayed two-axis and was never summed. Their library was deeper per component. Mine was stronger as a system: 179 tokens across four modes, 95 generated docs pages, a contrast gate in CI. The cross-cutting gaps were the real finding: RTL coverage 7 stories to 0, keyboard order 12 to 0, reduced motion 3 to 0, all in their favor.

The benchmark became instructions in the same document: steal this, and, just as explicitly, refuse that, with the reason each refused pattern was refused. Then it improved on itself within a day. The first proposal copied the peer’s named state stories; the version that shipped replaced most of them with something stricter and cheaper: coverage obligations derived from each component’s resolved TypeScript prop types, so a component that accepts a disabled prop owes proof of it, and RTL and reduced motion became global Storybook axes asserted once, for every component, instead of hand-written per story. Story counting, as the spec itself put it, is a proxy and not a measure.

A public registry that audits itself

Super AI Components has its own case study about the catalogue: 130 installable items derived from real AI products, and the inclusion test that re-cut them. What that case study does not tell is the machinery that let agents build it without wrecking it, because the machinery matured after it was written.

The repo now runs a three-layer defense, and the placement rule between the layers is the sharpest tool to come out of the summer. If an automated gate can catch a mistake, it is a gate in CI. If a gate cannot catch it but a dangerous tool call can be refused, it is a deny-hook, and every deny rule documents the exact bypass it was patched against. Only what survives both becomes prose in a skill. Rules stop being a style guide nobody reads and become the smallest possible amount of judgment, placed where it cannot be ignored.

The same repo is where parallelism got disciplined: up to twelve agent sessions at once, each in its own git worktree, each gated before merge by an eleven-step CI run that ends with a consumer test installing the built registry into a fresh app. A wave that used to take a working session now lands in one pass. The discipline exists because it failed once: a branch-bleed incident between concurrent sessions produced a standing worktree rule, written down the same day.

A personal kit that keeps itself honest

Minimal Design System is my own kit: 97 components on a three-tier token architecture, 331 variable declarations consumed only through a semantic layer, with a live Storybook and docs site. It is where the method stopped depending on my attention.

Three token tiers. Components read Layer 2 only.
Layer 1
Primitives

Raw color ramps. No component ever reads these.

Layer 2
Semantic

Surface, text, icon, button, border, status. The only place light and dark values are decided.

Layer 3
shadcn alias

Background, primary, muted and the rest, each pointing at a Layer 2 token. Never a value of its own.

The semantic layer owns the values and shadcn’s names alias onto it, so a stock component dropped in unmodified inherits the theme. A rebrand replaces ramps and nothing else.

Gates. Each fails the build on new violations; old debt sits in a baseline that may only shrink.
token gaterule recordsa story per componentcapability statestoken livenesstoken mirroraxe on every story, both themes
A change, end to end
write-time hooklint + types + gates + testspacked consumer harnesssix CI jobs

A contrast failure is treated as a design decision: the fix is proposed with measured ratios and waits for approval, and tokens are never quietly darkened to make a run green.

Minimal Design System architecture, drawn from the kit’s own Architecture page in Storybook.

Its capability contract is the piece I would show first. Components declare what they can do, and CI derives what each declaration owes: a component claiming keyboard support owes the story that proves it. Coverage stops being a number and becomes a list of specific debts. The debts that predate the rules live in ratchet baselines: three JSON files of grandfathered violations that new code cannot add to, so the number only goes down.

The honesty shows in the accessibility work. The axe suite ran 23 failing story files with 39 failing tests; one token-pair fix brought it to 17 and 32, and the improvement was verified by reverting the fix and re-running rather than trusting the changelog. The named-state story convention was piloted before being adopted, with an explicit bar: it stays only if it catches something the docs missed. It did, twice, in one afternoon: an icon-only component with no accessible name, and a docs page claiming a wrapping behavior the component did not have.

The method now polices this page

The test of a portable method is that porting it is boring. In the same pull request that added this page, this portfolio got its own token gate: a script encoding the site’s real contract, colors only through CSS variables, type only through the site’s text classes, shadows only where the system already grants them on hover. Forty-five files pass it clean. Sixty-eight pre-existing violations, mostly inline font sizes on older case pages, are grandfathered in a ratchet baseline that new code cannot grow.

The write-time half is the part I like most. A single global hook watches every file edit on my machine, walks up from the edited file to the nearest repo that owns a gate, and runs that repo’s own rules before the write lands. Policy stays in each repo; enforcement is generic; a repo without a gate is simply left alone. An agent that tries to hardcode a hex value into this site now gets stopped mid-edit, shown the violation, and pointed at the token it should have used. The page you are reading was written under that gate.

Reflection

What I would do differently.Close the loop on lessons faster. The client repo’s own plan ended with a step it never got: encoding the coverage mechanism back into the agent rulebook. The gap is documented, which is the method working, and unclosed, which is me. Guardrails that live only in a merged PR are one refactor away from being folklore.

What surprised me. How often the honest version of a metric is two numbers refusing to become one. The benchmark that refused a total is the same move as the coverage list that refused a percentage and the baseline that only counts downward. Every time I collapsed less, I learned more.

What I would keep. The placement rule. Gate what a script can check, deny what a tool call can catch, and spend prose only on what survives both. It is the first principle I have found that tells a designer exactly where their judgment belongs in an agentic build, and it is why three systems in ten weeks got safer as they got faster.

Unlisted. This case study is reachable only by URL and is not indexed. The client system is described at method level only.