Contributing
How to add a design-system component — from ADR to the quality gates.
The seven steps
Adding a component touches seven artifacts. The order matters: the ADR unblocks everything downstream, and the catalog is the source of truth for the docs site.
- ADR first. Modifying the barrel (src/index.ts) or patterns.ts — or adding any new DS component — requires an Architecture Decision Record per the repo escalation rules (see AGENTS.md). The ADR names the component, its layer, and its public API.
- Source. Create packages/design-system/src/components/<category>/<Name>/<Name>.tsx (+ .test.tsx beside it). TypeScript strict, no any, tokens only — no raw hex or ad-hoc Tailwind values.
- Barrel export. Export the component from src/index.ts. This is the only legal import surface — and remember the barrel itself is ADR-gated.
- patterns.ts entry. Add a full PatternMeta entry to src/patterns.ts (slug, name, category, path, description, status, props, interface, assertions, ariaRole, aiHints, examples, antiPatterns, tokens). The entry shape is documented below — the docs pages render from this catalog.
- Regenerate the .ai index. Run the TWO-STEP pipeline: pnpm exec tsx scripts/build-agent-index.ts && pnpm exec tsx scripts/sync-index-from-patterns.ts. One script alone leaves the index stale.
- Docs + stories + test. Add docs/components/<slug>.mdx (props table matching the source interface), a story if the component is visual, and a unit test beside the source. The docs-consistency gate (pnpm ds:consistency) fails on divergence between these representations.
- Run the gates. pnpm check:all must be green before the branch can be reviewed (add --build for the build gates). Conventional commits, one concern per branch, qa-dev review before merge into experimental.
The patterns.ts entry shape
Every field below is required for implemented components (tokens optional when the component reads no DS tokens):
{
slug: "mywidget", // kebab-case, unique, = docs route
name: "MyWidget", // PascalCase, = export name
category: "atoms" | "molecules" | "organisms" | "templates",
path: "patterns/<category>/<slug>.html",
description: "One-line summary shown as the page header.",
status: "implemented", // or "planned" | "deprecated"
props: [ { name, type, required, default, description } ],
interface: "interface MyWidgetProps { ... }", // stringified TS
assertions: [ { type: "aria" | "type", rule, reference } ],
ariaRole: "img" | null,
aiHints: "When an agent should reach for this component.",
examples: [ "<MyWidget />" ],
antiPatterns: [ "..." ],
tokens: [ "ep-mywidget-fg" ], // DS tokens read/defined
}Barrel modification rules
The barrel (packages/design-system/src/index.ts) and patterns.ts are the public API of the design system. Changing either — adding, renaming, or removing exports — requires an ADR and a version bump. Deep imports are lint-banned; consumers must import from the package root only.
Corollary: never re-export a storefront component from the DS barrel, and never move an export without a deprecation window.
Index regeneration
The agent index (.ai/INDEX.json) is generated — never hand-edit it. After any patterns.ts change, run both scripts in order:
pnpm exec tsx scripts/build-agent-index.ts pnpm exec tsx scripts/sync-index-from-patterns.ts
build-agent-index.ts rebuilds component metadata and relationship graphs; sync-index-from-patterns.ts reconciles it with patterns.ts. Skipping the second step causes stale-lease and parity errors in the DS gates.
Quality gates
The commands below must pass before review:
pnpm check:all # 21 static gates (imports, stylelint, R-metrics, drift) pnpm check:all --build # + tsc / medusa / next build gates pnpm ds:consistency # 3-layer docs consistency gate
Exit 1 from any gate means the branch is not pushable. pnpm check:all