Architecture
Draft. The prose on this page is under review.
This page is the machinery behind the components: where each kind of file lives, what is generated from what, and which check fails when any of it goes out of step.
The short version: the catalog manifest is the one list of what exists, every component ships with a story and a written contract, generated files are compared with their sources on every run, and 12 gate steps hold all of that in place. Read as far as you need. Every section adds detail to that paragraph and none of them changes it.
Every number on this page is counted from the repository by a script and checked by a test. None is typed by hand.
1The build loop, and the loop that is missing
One loop runs today. A change starts from the written contracts, produces a component together with its story, its documentation and its registry entry, passes the gates locally and in CI, and ends at a person.
Build loop
1Read first
The map, the build brief, the routing table.
2Scaffold
Component, story, documentation and registry entry, together.
3Write the judgment down
When to use it and what to avoid, each with its reason.
4Audit the look
The anti-slop checklist, before building and again before done.
5Run the gates
Locally, in the workflow's order, from the repository root.
6A person reviews
Gates settle what a machine can settle. Review spends its attention on fit and hierarchy.
When review rejects something, fixing it is half the job. The other half is a new rule or gate that fails the next time.
Audit loop
Not built
Nothing re-checks main on a schedule, and nothing compares production with main. Deploys are manual, so the two can drift apart unseen.
The missing loop matters. Gates run when something changes. Nothing re-checks the main branch on a schedule and nothing compares production with it, and because deploys are manual the two have drifted apart before. Closing that gap is planned work.
2What the system is made of
| Kind | What it is | Where it lives |
|---|---|---|
| Instructions | A map every session reads first. It points at the contracts and restates none of them. | CLAUDE.md |
| Build briefs | The house contract each component and block is built to. | docs/design-system/component-build-brief.md |
| Rules | 20 typed records of what generated UI may not do, 17 of them blocking. | packages/ds-rules/src |
| Skills | 4 runnable procedures: build, integrate, run the gates, audit the look. | .claude/skills |
| Manifest | The single list of what exists: 118 shipped items across 12 primitives, 93 components and 13 blocks. | apps/docs/lib/catalog.manifest.ts |
| Contracts | 118 usage contracts, one per item, derived from its guidance module. | apps/docs/registry/super-ai |
| Stories | 118 story files. Declared-state stories restate the types. Case stories record the situations a component really meets. | apps/storybook/src/stories/super-ai |
| Prose pages | 34 pages of foundations, patterns and content guidance. | apps/storybook/src/stories |
| Specs and plans | Dated decisions, written before building. | docs/superpowers/specs |
| Gates | 12 steps that every change passes. | .github/workflows/ci.yml |
3What is generated from what
Several files in this repository are outputs. Nobody edits them. A command writes each one from its source, and a test or a gate compares the two on every run, so a stale output fails and cannot go on describing an older tree.
What
shadcn adddownloads. Built fresh in CI and never committed.- Source
apps/docs/registry/super-ai- Output
apps/docs/public/rNot committed.- Written by
pnpm build:registry- Held by
apps/docs/scripts/consumer-test.sh
The contracts layer. One guidance module per component is the source for all of it.
- Source
apps/docs/content/components- Output
apps/docs/registry/super-ai/<name>.meta.jsonapps/docs/index/components.toonapps/docs/public/llms.txtapps/docs/public/llms-full.txtapps/docs/public/llms- Written by
cd apps/docs && pnpm contract:emit- Held by
apps/docs/scripts/lib/contract-emit.test.ts
The rule records as JSON, which is what the detector reads.
- Source
packages/ds-rules/src- Output
packages/ds-rules/rules/core.jsonpackages/ds-rules/rules/local.json- Written by
pnpm --filter ds-rules rules:emit- Held by
packages/ds-rules/src/emit.test.ts
The wiring from each catalog item to its demo and its documentation.
- Source
apps/docs/lib/catalog.manifest.ts- Output
apps/docs/lib/demos.generated.tsapps/docs/lib/docs.generated.ts- Written by
cd apps/docs && pnpm gen:wiring- Held by
apps/docs/scripts/check-contract.mts
The numbers on these pages, counted from the tree.
- Source
apps/docs/scripts/lib/system-facts.ts- Output
apps/docs/content/system/facts.json- Written by
cd apps/docs && pnpm facts:emit- Held by
apps/docs/scripts/lib/system-facts.test.ts
The numbers on this page work the same way. They live in apps/docs/content/system/facts.json, and they are as of the last time that file was written. A test fails when the tree has moved past it.
4The gates
Each step below runs in CI and, in the same order, in the local script at .claude/skills/gate-run/run-gates.sh. The order is a list in one place, and a test fails when the workflow, the script and this page disagree.
- 1
Install from the lockfile
pnpm install --frozen-lockfileinstall
- 2
Lint
pnpm lintstatic
- 3
Formatting
pnpm format:checkstatic
- 4
Types
pnpm typecheckstatic
- 5
Token contract
pnpm check:tokensstatic
- 6
Manifest, story and docs contract
pnpm check:contractstatic
- 7
Unit tests and ratchets
pnpm testtest
- 8
Registry build
pnpm build:registrybuild
- 9
Full build
pnpm buildbuild
- 10
Smoke test of every page
Playwright smokebrowserexercises the product
- 11
Accessibility and interaction
Storybook a11y + interactionbrowserexercises the product
- 12
Consumer install
Consumer install testbuildexercises the product
1Install from the lockfile
pnpm install --frozen-lockfileEvery gate below runs against the dependency versions the lockfile records, so nothing passes on a newer package than the one that ships.
pnpm-lock.yamlThe resolved version of every dependency.
2Lint
pnpm lintCatches unescaped quotes in JSX prose and unused code before a reviewer has to.
apps/docs/eslint.config.mjsRules for the docs app and the registry sources.apps/storybook/eslint.config.mjsRules for the stories.
3Formatting
pnpm format:checkKeeps a diff about the change. A generated file that must match its generator byte for byte is listed as ignored and is never reformatted.
.prettierrc.jsonThe one formatting configuration..prettierignoreThe generated files whose emitters own their shape.
4Types
pnpm typecheckA prop a component does not declare is an error here, in the registry sources, the stories and the rule records alike.
apps/docs/tsconfig.jsonThe docs app, the registry and the scripts.apps/storybook/tsconfig.jsonThe stories, against the real component types.packages/ds-rules/tsconfig.jsonThe rule records.
5Token contract
pnpm check:tokensNo raw colour, palette class, gradient or banned motion utility reaches a registry component, so a consumer's theme restyles everything they install.
packages/ds-rules/rulecheck.mjsThe detector.packages/ds-rules/rules/core.jsonThe bans shared with the sibling design system.packages/ds-rules/rules/local.jsonThe bans specific to this repository.
Does not see: It reads one class string at a time. Muted text in a child whose ancestor paints the muted surface passes here, and every contrast bug that shipped had that shape. The accessibility step below is the backstop.
6Manifest, story and docs contract
pnpm check:contractEvery catalog item has the story exports its declared states promise, documentation whose citations resolve, and dependencies reconciled from real imports.
apps/docs/scripts/check-contract.mtsManifest, story and docs agreement, and the generated wiring files byte for byte.apps/docs/scripts/check-citations.mtsEvery backticked citation in the component docs.apps/docs/scripts/reconcile-deps.mtsDeclared dependencies against what the source really imports.
7Unit tests and ratchets
pnpm testThe ledgers below may shrink and never grow, derived files must match their sources, and the numbers on this page must match the tree.
apps/docs/lib/catalog.manifest.test.tsThe catalog is complete and the cut families stay cut.apps/docs/scripts/new-component.test.tsThe scaffolder never emits a state nameddefault.apps/docs/scripts/lib/a11y-ratchet.test.tsThe accessibility exclusion list only shrinks.apps/docs/scripts/lib/story-coverage.test.tsUnmet story obligations only shrink.apps/docs/scripts/lib/contract-coverage.test.tsUnwritten contract fields only shrink.apps/docs/scripts/lib/cssvars-liveness.test.tsEvery CSS variable a component reads resolves, and none is declared unread.apps/docs/scripts/lib/contract-emit.test.tsInstalled contracts, the routing table and thellms.txtcorpus match the guidance modules.apps/docs/scripts/lib/claude-md.test.tsThe instructions file stays under its byte ceiling, and each rule in it names a gate.packages/ds-rules/src/emit.test.tsThe emitted rule JSON matches the typed records.apps/docs/scripts/lib/system-facts.test.tsThe numbers on these pages match the tree.apps/docs/content/system/gates.test.tsThis roster matches the workflow and the local gate script.apps/docs/content/system/claims.test.tsCounts typed into prose elsewhere match the tree.apps/docs/content/system/pages.test.tsThese pages cite real files, type no numbers and keep the writing rules.
Ratchets:
apps/docs/cssvars-liveness.baseline.json,apps/docs/scripts/lib/contract-coverage.baseline.json,apps/docs/scripts/lib/story-coverage.baseline.json,apps/storybook/a11y-exclusions.baseline.json8Registry build
pnpm build:registryRegenerates what consumers install. A stale registry is invisible locally and broken for them.
apps/docs/scripts/gen-wiring.mtsThe generated wiring between manifest, demos and docs.apps/docs/scripts/gen-registry.mtsThe registry index thatshadcn buildreads.
9Full build
pnpm buildThe docs app and Storybook both compile from the same sources the registry ships.
apps/docs/next.config.tsThe docs app build.apps/storybook/.storybook/main.tsThe Storybook build.
10Smoke test of every page
Playwright smokeEvery component page renders in a real browser without a console error.
apps/docs/e2e/smoke.spec.tsOne test per catalog item, plus the system pages.apps/docs/playwright.config.tsServes the built app on its own port.
Does not see: It serves the prebuilt app. Edit a source file without rebuilding and a green run proves nothing.
11Accessibility and interaction
Storybook a11y + interactionEvery story passes axe and its own interaction assertions in Chromium. This is the step that catches the contrast shape the token gate cannot see.
apps/storybook/vitest.config.tsRuns every story in a browser, with the exclusion list the ratchet guards.
12Consumer install
Consumer install testInstalls every item into a fresh app with
shadcn addand builds it. A component that looks right here and breaks there has failed.apps/docs/scripts/consumer-test.shThe install and the build, end to end.
Two properties are deliberate. 4 ledgers are ratchets: the accessibility exclusions, the unmet story obligations, the unwritten contract fields and the CSS variable debts may shrink and may never grow. And a scanner earns trust by failing first: every rule record ships a fixture that must trip it, because a scan that finds nothing and a scan that looked at nothing print the same result.
5Usage contracts
Every item has a guidance module, and its contract is derived from that module. These are the fields an agent reads before placing a component.
| Field | What it holds |
|---|---|
purpose | The job the component does. |
usage | When to reach for it. |
variants | Each variant with its intent: when to pick it. |
insteadUse | Near twins, and when to reach for them instead. |
dos and donts | What to do and what to avoid, as sentences. |
accessibility | Keyboard, screen reader and focus behaviour. |
pitfalls | Traps that have bitten, including classes the component does not write. |
states | The declared states, each with a matching story. |
anatomy | Named parts, anchored to shipped data-slot values. |
A field nobody has written yet is recorded as unwritten. It is never filled with an empty value, and the count of unwritten fields is one of the ratchets.
6Stories and coverage
A story file holds two kinds of story. Declared-state stories restate the types: one export per state the manifest declares, and a gate fails when one is missing. Case stories are the only place a component's real situations are written down: long content, an empty list, a narrow screen.
Every story runs in Chromium with axe. That step is the backstop for the contrast shape the token gate cannot see, and its exclusion list is a ratchet.
7A change, end to end
- Read the map in
CLAUDE.md, then the build brief, then the routing table, so nothing gets built twice. - Scaffold the component with
pnpm new:component. The files it writes move together. - Write the judgment into the guidance module: when to use it and what to avoid, each with a reason.
- Run the anti-slop audit before building and again before calling it done.
- Run every gate locally, in the workflow's order, from the repository root.
- Open a pull request from a branch. Nothing is committed to the main branch directly.
- A person reviews. Merging does not deploy. Production ships by hand.
8The principles underneath
The registry is the product. A component that looks right in Storybook and breaks on install has failed.
A list of gates mirrors the workflow, in the workflow's order. CI stops at the first failure, so one red gate hides every gate behind it.
A green run can prove nothing. A test that serves a prebuilt app says nothing about source edited since the build.
An exclusion list may only shrink. Adding a file to silence a failure defeats the gate.
Blocks compose. When a composed component does not fit, the gap gets reported, and the component does not get reimplemented.
A number typed into prose goes stale. Count it from the tree or leave it out.