Skip to content
fearchitect
Styling & Design Systems

Design Systems

A shared product — tokens, components, docs, and governance — at scale.

By Abas TurabliReviewed

Summary

A design system is a versioned product consumed by product teams: it packages design tokens, a component library, documentation, and a contribution model. The cost is real — a dedicated team of 2–4 engineers is the industry baseline. The payoff is consistency at scale and faster product iteration once adoption crosses a threshold.

Jump to the interview angle

A design system bundles four layers into one versioned package: design tokens (color, spacing, typography as CSS custom properties or JSON), a component library (accessible, token-consuming UI primitives), documentation (live playground, usage guidelines, accessibility notes), and a governance model (who can merge, how to request new components, how breaking changes land).

The package ships as an npm package — e.g. @acme/ui — so consuming teams pin a version and upgrade deliberately. Without semver and a changelog, it is not a design system; it is a shared folder.

What a design system contains

  • Design tokens: named CSS custom properties (--color-brand-500) generated from a source-of-truth JSON file.
  • Component library: accessible, token-driven primitives published as an npm package with TypeScript types.
  • Documentation site: live Storybook or equivalent with prop tables, usage rules, and a11y guidance.
  • Versioning: semver — patch for bug fixes, minor for new components, major for breaking API changes.
  • Governance: a contribution guide and RFC process so teams can propose without bypassing review.
Tokens flow into the component package; product teams pin a version and consume both.

Shipping a breaking change safely

  1. 1

    Deprecate, don't delete

    Add a console.warn or TypeScript @deprecated tag in the current minor. Give consumers at least one release cycle before the breaking change ships.

  2. 2

    Write a codemod

    Use jscodeshift or ts-morph to automate the migration. A codemod turns a breaking change from a blocker into a one-command upgrade for most teams.

  3. 3

    Cut the major version

    Bump to the next major via semver, publish a MIGRATION.md, and list the codemod command. Pin old major in an LTS branch only if the org has strict upgrade policies.

  4. 4

    Announce and track adoption

    Post in #design-system with the migration command. Track the old API usage via a custom ESLint rule or import analysis until adoption reaches zero.

Build vs. adopt an existing system

Pros

  • Consistent UI across products without per-team CSS drift.
  • Accessibility handled once in the library instead of per component per team.
  • Tokens enable a single theming change to propagate everywhere instantly.
  • Frees product teams from low-level UI work once adoption is high.
  • Shared vocabulary speeds design-to-engineering handoff.

Cons

  • Requires 2–4 dedicated engineers; an unmaintained system is worse than none.
  • Breaking changes need codemods and deprecation cycles — releasing slows down.
  • Product teams must wait for the system to support their use case or fork.
  • Adoption is voluntary until mandated; expect a long tail of inconsistent usage.
  • Wrong abstractions calcify fast — early API mistakes cost compounding migration work.

The maintenance trap

Teams build a component library, then dissolve the working group. Within six months, product teams fork components and the system fragments. A design system needs a named owner, a public roadmap, and a contribution SLA — or it should not be built. Adopting Radix UI or shadcn/ui with custom tokens is a valid alternative for smaller orgs.

Interview angle

Interviewers probe whether you treat a design system as a product, not a repo dump. Discuss semver, breaking-change codemods, adoption metrics, and when NOT to build one.

Soundbite: "A design system is a product with consumers; ship it like one — semver, changelogs, codemods for breaking changes."

Key terms

Design tokens
Named, platform-agnostic values (color, spacing, type) stored as JSON and compiled to CSS custom properties or platform constants.
Semver
Semantic versioning: patch.minor.major — major bumps signal breaking API changes that require a migration.
Codemod
An automated script (jscodeshift, ts-morph) that rewrites source code to migrate a breaking API change.
Contribution model
The RFC and review process defining who can add or change components and under what conditions.
Adoption rate
Percentage of product surfaces using the system's components; tracked to justify maintenance cost and deprecate forks.

Further reading

Search fearchitect

Jump to a topic, mode, or action.