Design Tokens at Scale: One System, Five Brands

How a three-tier token architecture let one design system serve five product brands without a single hardcoded color.

Design Tokens at Scale: One System, Five Brands
Did you enjoy this article? Share it:

When the second brand arrived, our design system almost collapsed. The components were solid — battle-tested, accessible, documented. The problem was that every color, radius, and shadow was a decision baked into them. Brand two wanted warmth where brand one wanted austerity, and the only tool we had was a fork. This is the story of the rebuild, and the three-tier token architecture that now serves five brands from one codebase.

Why one tier fails

A flat token list — brand-blue-500, spacing-4, radius-lg — feels organized right up until someone asks what happens when the accent color must differ per brand. Flat tokens name values, but components need to reference intent. The moment intent and value are the same token, every brand difference becomes a component change, and every component change is a regression risk multiplied by the number of brands.

Three tiers or bust

Primitive tokens name raw values and nothing else: blue-600 is a hex code with no opinions. Semantic tokens name intent: surface-raised, accent-primary, text-danger, border-subtle. Component tokens name usage: button-primary-bg, card-border-radius. The dependency flows one way — components consume component tokens, component tokens reference semantic tokens, semantic tokens resolve to primitives.

Brands override exactly one layer: the semantic tier. Brand A maps accent-primary to violet-600; brand B maps it to amber-500. Nothing downstream changes. In two years of running this architecture, we have not forked a single component for brand reasons — the middle tier absorbs every difference.

:root {
  /* primitive */
  --violet-600: #7c3aed;

  /* semantic - the only tier brands override */
  --accent-primary: var(--violet-600);
  --surface-raised: var(--gray-50);

  /* component */
  --button-primary-bg: var(--accent-primary);
}

Naming is governance

The hardest part is not the tooling — it is agreeing what intent names mean and defending them. We keep a one-page constitution: semantic tokens describe roles a designer would recognize, never values, never components. Proposals for new tokens require a use case that two existing tokens cannot cover. It sounds bureaucratic; it is the reason the system still has 60 semantic tokens instead of 600.

Automate the guarantees

Every brand override runs through a pipeline that checks contrast pairs automatically — text tokens against their permitted surfaces, WCAG AA as the floor. A brand cannot merge a palette that produces illegible buttons, because the CI fails before a human ever reviews it. The same pipeline emits the tokens as CSS custom properties, iOS asset catalogs, and Android resources from one source of truth.

The payoff

A new brand now ships in days: one semantic token file, an automated contrast report, zero component forks. Designers prototype brand variations by editing variables in the browser. And the design system team stopped being a bottleneck for brand work entirely — the system stopped being a style guide and became infrastructure.

Did you enjoy this article? Share it:
Elena Rostova

Elena Rostova

Verified Author

AI Researcher & Product Architect. Exploring on-device machine learning, local LLMs, and high-converting UX design.

📍 Berlin, Germany 🌐 Website 🐦 Twitter
NEWSLETTER

Unlock Exclusive Tech & Creator Insights

Join thousands of readers. Get our latest deep-dives, guides, and tech analysis delivered straight to your inbox.

Great! Check your inbox to confirm your subscription.

Discusión de los miembros

0 comentarios

Comienza la conversación

Hazte miembro de Vanta Tech & Creator para poder comentar.

100%