5 min read

What a design system actually needs to work

A design system is a shared set of components and rules, defined once and referenced everywhere, rather than a folder of past screens to copy from. The difference matters the first time a brand color changes: with a system, it’s a single edit; without one, it’s a search through every page that used that color separately.

Tokens, not hardcoded values

Design tokens are the actual mechanism: colors, spacing, and type sizes stored as named values (color.primary, space.md, font.body) and referenced by every component, rather than typed in individually wherever they’re needed.

  • A rebrand becomes a change to the token file, not a pass through every screen. Change the value behind color.primary once, and every button, link, and highlight that references it updates at the same time.
  • A spacing inconsistency between two screens usually means someone typed a raw pixel value instead of using the token, which is exactly the bug a token system is built to prevent.
  • Tokens work across both the design file and the codebase when they’re set up correctly, so a designer and a developer are referencing the same source rather than two versions that can drift apart.

Handoff: the same names on both sides

The recurring failure in design-to-development handoff isn’t unclear intent, it’s inconsistent naming. A component called “PrimaryButton” in the design file and “btn-cta” in the codebase forces a developer to guess whether they’re the same thing.

  • We name components identically in both places, and match their configurable properties (a button’s size, variant, and state) one-to-one between the design tool and the code component.
  • This turns handoff from an interpretation exercise into a lookup: the developer finds the matching component and its exact props already defined, nothing to infer.
  • Documenting each component with its variants and states in one place, a living reference rather than a static handoff document, keeps this lookup accurate as the system evolves instead of going stale after the first release.

Accessibility lives in the component, not the page

Building accessibility into the component library means every screen that uses it inherits the behavior automatically, instead of a designer or developer re-deciding contrast and keyboard behavior on every new screen.

  • Every interactive component ships with its focus state, its keyboard behavior, and a contrast ratio that already passes, so a new screen built from the system starts compliant rather than needing a separate accessibility pass.
  • Text components carry the correct underlying HTML tag by default (an h2 stays a real heading, not a styled div), which is what lets both screen readers and search engines read the page’s structure correctly.
  • This is different from an accessibility check applied late: the check only needs to happen once, at the component level, not once per page that uses it.

A system needs an owner, or it decays

A design system left with no owner tends to accumulate duplicate one-off components anyway, because it’s often faster for one person to build a new button than to find, understand, and reuse the existing one.

  • We assign a specific person or team responsible for reviewing additions and preventing duplicates, not a shared, unowned responsibility that nobody actually holds.
  • Changes get versioned like a software library: a patch for a bug fix, a minor version for a new component, a major version for a change that breaks existing usage, each with a changelog entry stating what changed and what it affects.
  • A breaking change gets a deprecation notice and a window before the old version stops working, so teams consuming the system have time to update rather than breaking on a Monday morning with no warning.

Where AI actually helps

We use Claude Code directly in this workflow, and the place it earns its keep isn’t generating a design system from scratch, it’s lowering the friction that causes the duplicate-component problem described above in the first place.

  • Catching near-duplicates before they get built. A new component request can be checked against the existing library semantically, not just by exact name match, so “we need a card with an image and a badge” gets matched to the existing Card component instead of becoming a second one.
  • Scaffolding a new component from the existing tokens and patterns. When something genuinely new is needed, generating the first draft directly from the token file and a similar existing component is faster than hand-rolling one from nothing, which removes the actual incentive behind most one-off components.
  • Flagging hardcoded values during review, a raw hex code or pixel value that should have referenced a token, caught before merge instead of shipped and found later during a visual audit.
  • Keeping documentation from going stale. Regenerating a component’s documented props and states whenever the component itself changes, instead of a static handoff doc that quietly stops matching the real component after the second release.

None of this replaces the owner described above. A person still has to decide whether a request is genuinely a new pattern or a duplicate in disguise, AI narrows the distance between “reuse the existing component” and “just build a new one,” it doesn’t remove the judgment call.

Where it isn’t worth it

Building a full design system has real upfront cost, and it isn’t worth that cost for a single landing page or a short-lived campaign site with no reuse ahead of it. It earns its cost once a product has enough screens, or enough people building on it, that inconsistency and duplicated work are already happening without one.

Share

X LinkedIn

Start the Conversation


Whether you’re a founder building toward your next milestone, a creator building for a client, or an agency looking for a reliable delivery partner, we’re happy to talk it through.