Every team eventually ships Button, ButtonNew, PrimaryButton, and MarketingCTA that differ by two pixels and a shadow.

That is not flexibility. That is sprawl — and it taxes every future feature with decision fatigue, inconsistent accessibility, and endless one-off CSS. Design systems work when the default is reuse, and new primitives require a case.

White blocks with one indigo block aligned

Alignment is the product. Drift is the default without governance.

Why sprawl happens

  • Deadlines reward “just copy the button and tweak”
  • Designers invent visual variants without engineering review
  • No ownership of deprecation
  • Storybook exists but is not part of the definition of done
  • Tokens are weak, so components absorb one-off values

Addition checklist

Library governance diagram

Before a new component or variant:

  1. Which user job is not met by existing primitives?
  2. Can tokens or props extend an existing component?
  3. Who owns accessibility and keyboard behavior?
  4. What is the deprecation plan for what it replaces?
  5. Is there a docs/Storybook entry in the same PR?

No answer → no merge.

Measure adoption

Track the percentage of UI using system components vs one-offs (even approximately via codemods or package imports). Celebrate deletions of variants. A healthy library shrinks sometimes.

API design for components

Prefer composition and variants over parallel components:

  • Button with variant and size beats four near-copies
  • Document do/don’t examples
  • Forbid styling hacks that pierce encapsulation for “just this page”

Closing

Treat the library like a product with a ruthless editor. Fifteen buttons is not a system; it is a junk drawer with TypeScript types.


Need design system governance? Start a project inquiry.

Contribution model

  • RFC for new components above a complexity threshold
  • Office hours for “should this be a variant?”
  • Design + eng co-ownership of the release train

Breaking changes

Semver the library. Provide codemods for renames when you can. Never silently change accessibility behavior in a patch.

The “marketing exception”

Marketing will always want a one-off. Channel it: temporary local composition using public primitives, or a time-boxed experiment component with a delete date. Never permanent forks without review.

Visual QA

Chromatic/Storybook visual tests catch accidental variant drift. Wire them to the packages that power production, not a toy Storybook that diverges.

Discovery questions we ask

  1. What breaks if this is wrong in production next week?
  2. Who is paged, and is that written down?
  3. What does “done” mean in a checklist a stranger can run?
  4. Which metric proves the practice is working a month later?

If those answers are vague, the write-up is not finished — and neither is the system.

How this fits the rest of the journal

Pair this note with post-launch ownership, performance budgets, and technical SEO where relevant. Most failures are cross-cutting: a migration without redirects, a flag without expiry, a form without rate limits.

Closing reminder

Write the operating rules while the team that built the feature still remembers why. That is cheaper than reverse-engineering six months later during an outage.