Soren Learning

Chapter 1

What a Design System Actually Is for Engineers

Listen to this article

Before we touch a single token or write a Button component, the term "design system" needs to mean something specific. The phrase has been so over-used — by designers, by component-library marketers, by every team that ever shipped a Figma file with a brand colour — that engineers approaching it fresh often can't tell whether they need one, what it would do for them, or how to start.

This chapter does three things. It defines a design system precisely from an engineering point of view. It separates the four parts that make one work. And it tells you when you actually need one — because building a design system before you need one is itself a costly anti-pattern.


A working definition

The cleanest definition I've found, stripped of marketing:

A design system is a contract between the people who design an interface and the people who build it, expressed as code. It is the canonical source for tokens, components, patterns, and documentation that any product in the organization can — and should — consume.

Three words in that definition do the heavy lifting:

  • Contract. A design system is a promise that "primary button" means the same thing on the marketing site, the dashboard, and the mobile web. If team A interprets it differently from team B, the system has failed regardless of how pretty the Figma file is.
  • Code. A Figma file is not a design system. A document is not a design system. The system exists in production code that consumers import. Without that, you have a style guide, which is a different (and weaker) artifact.
  • Canonical. There is one source of truth. Multiple parallel "kinda-design-systems" — one per team, one per product — defeat the entire purpose. Most failed design systems failed at this step, not at any of the technical ones.

If your "design system" is missing any of those three, it isn't yet what this series means by the term.


The four parts that make a system work

A design system in production is composed of four distinct things, each shipping separately but reinforcing each other.

1. Tokens

The atomic units. A token is a named, semantically-meaningful value: color.primary, spacing.md, radius.sm, font.body.lineHeight. Tokens are the lowest layer — every component is built from them.

Tokens are what allow a design change ("our primary blue is now indigo-600 not blue-600") to ripple through the entire product without touching every component. Chapter 2 goes deep on tokens.

2. Components

Reusable UI elements with stable APIs: Button, Input, Dialog, Tabs, Card. A component encapsulates a token combination plus behaviour, plus accessibility, plus all the states (hover, focus, disabled, loading).

Components are what consumers actually import. They're the API surface of the system. Chapter 3 covers component API design.

3. Patterns and documentation

A pattern is a recommended composition of components for a recurring UI problem: "this is how a settings form should look", "this is the canonical empty state". Patterns live as documented examples (often in Storybook — chapter 4) and prevent every team from reinventing the same compositions.

Documentation makes the system findable and teachable. A perfect component nobody can find is functionally invisible.

4. Governance

The rules and processes around the system: who can add a component, how breaking changes are approved, what the versioning policy is, how feedback is collected, how migrations are coordinated.

Governance is the part most engineering teams underestimate. A system without governance becomes a graveyard of half-finished components within 18 months. Chapter 5 covers versioning, which is the most concrete piece of governance.

Going deeper. A useful frame: tokens are the atoms, components are the molecules, patterns are the organisms, and the system itself is the organism's environment. This is loosely the Atomic Design hierarchy popularized by Brad Frost — useful as a mental ladder, not literal as a folder structure. Most modern systems collapse the lower layers and live mostly at component + pattern levels.


What a design system isn't

Three things commonly mistaken for design systems:

Not just a CSS framework

Tailwind is not a design system. Tailwind is a toolkit — a way to express a design system in CSS — but the system itself is the set of decisions about which tokens you use, which components you build, and how they compose. Two teams using Tailwind can ship completely different products with completely different visual languages.

That said, Tailwind's defaults are essentially a small design system — its colour palette, type scale, and spacing scale are all tokens. We'll lean on those defaults heavily because they're sensible and free.

Not just a component library

A bag of <Button>, <Input>, and <Modal> components without tokens, without docs, without governance is a component library, not a design system. It's a useful artifact — but it's missing the contract layer that makes a design system valuable.

shadcn/ui, interestingly, blurs this line: it ships components but explicitly says "you own the code." The design system is the combination of shadcn's component patterns plus the tokens and decisions you wrap around them. Chapter 7 will revisit this distinction.

Not just a Figma library

Designers will sometimes refer to a Figma file with components and styles as "the design system." From the engineering perspective, this is the spec, not the system. The system is the code that implements the spec. Until that code ships and is consumed, the design system doesn't exist as far as your runtime is concerned.

The healthy state: Figma is the design source of truth, the design system code is the engineering source of truth, and tokens are the pipeline that keeps them in sync. We'll cover that pipeline in chapter 2.


When do you actually need one?

This is the question most "design system advocacy" content avoids, because the honest answer is "later than you think."

The cost side

Building a real design system — not a half-baked one — costs:

  • 3–6 engineer-months for the initial spine (tokens + 10–20 core components + Storybook + initial docs)
  • Ongoing 10–30% of one engineer's time for maintenance: bug fixes, new components, version coordination, supporting consumers
  • Coordination overhead across consumer teams: every breaking change needs a migration plan
  • Governance overhead: someone has to say "no" to one-off requests, which is a soft skill more than an engineering one

That's not free. For a single-team, single-product startup with 6 engineers shipping an MVP, the cost is rarely justified.

The benefit side

The benefit shows up specifically when:

  • Multiple products share an organization — and need to feel like one company.
  • Multiple teams ship UI in parallel and the visual divergence is starting to embarrass everyone.
  • The product surface is large enough that "consistency by code review" no longer scales.
  • You're hiring frequently and onboarding ramp-up is dominated by "how do we do X?" questions where X is a UI pattern.

If none of those apply, don't build a design system yet. Use Tailwind defaults, copy a few shadcn/ui components, add tokens for your brand colours, ship the product. You're 80% of the way there with 5% of the work.

The premature design system anti-pattern

The most expensive design-system mistake teams make is starting too early. A 4-engineer team with one product spends two months building the perfect token taxonomy, ships 30 components nobody uses yet, and discovers that real product needs don't match the system they built. They throw it away in v2 and start over.

A useful rule of thumb: don't build the design system until you have at least three real consumers shipping production UI from it. Real consumers force real decisions. Without them, you're optimizing for imagined needs.


The minimum viable design system

When you do start, start small. The minimum viable design system is roughly:

  • Token layer: colours, spacing, typography. Three categories, ~30 tokens total. Don't over-engineer.
  • 5–10 core components: Button, Input, Label, Card, Dialog, Tabs, Toast, Badge. These cover ~80% of UI.
  • A simple docs site: Storybook is the default — chapter 4 covers it. A README per component is acceptable when starting.
  • Semver in your package.json and a CHANGELOG.md. That's the entire governance layer until you outgrow it.

Ship that. Add components on demand as real product needs surface them. Resist the temptation to build "the perfect Calendar component" before any product needs a calendar.

Going deeper. Some of the most successful design systems started as internal scaffolding for a single product before being elevated to organization-wide systems. Polaris (Shopify) started as the Shopify admin's UI. Primer (GitHub) started as github.com's UI. Material Design started as Android's UI. They became systems by extracting what worked, not by designing a system in the abstract.


What this series is and isn't

To set expectations:

This series is:

  • An engineering-first treatment of the system as production code.
  • Opinionated about defaults (React + Tailwind + shadcn/ui) and about which patterns survive scaling.
  • Anchored in real systems you can study (shadcn, Radix, Polaris, Primer).
  • Written assuming you'll work through the running Button example, which will get progressively richer.

This series isn't:

  • A treatment of design system design (visual language, brand strategy) — that's a separate book.
  • A tour of every component library — we focus on patterns, not products.
  • A multi-platform guide — we cover web; iOS, Android, and React Native have many of the same principles but different mechanics.
  • A Figma tutorial.

What you should walk away from chapter 1 with

Three ideas to carry into the rest of the series:

  1. A design system is a contract, expressed as code, that's canonical. Tokens + components + docs + governance. If you're missing any of those four, you don't have a system yet.
  2. You probably don't need one as early as you think. The cost is real; the benefit only kicks in when you have multiple consumers. "Don't build the system before you have three real consumers" is a rule of thumb worth holding to.
  3. When you do build one, start tiny. A token layer + 5–10 components + Storybook + semver is a minimum viable system. Add more on real demand.

The next chapter goes deep on the foundation layer: design tokens, what they actually are, and the pipeline that turns them into the values your code consumes.


Next up — Chapter 2: Design Tokens — The Bridge Between Designers and Developers. The atomic layer of any design system, the pipeline that delivers them, and why naming a token is harder than it looks.