Design systems

Building a scalable design token architecture

A comprehensive guide to structuring design tokens across multiple layers, enabling seamless theming and consistent UI at every scale.

Design tokens are the atomic building blocks of a design system. They represent the smallest decisions about color, spacing, typography, and motion, stored as platform-agnostic key-value pairs. When implemented well, they become the single source of truth that bridges the gap between design tools and production code.

But as organizations grow and products multiply, a flat list of tokens quickly becomes unmanageable. Teams need a structured architecture that supports theming, white-labeling, and multi-platform delivery without drowning in complexity. This article explores a proven three-layer approach used by teams at scale.

Why design tokens matter

Every design system eventually faces a consistency crisis. Designers specify one shade of blue, but engineers implement three slightly different variants. A button radius changes in Figma, but the corresponding CSS value stays the same for months. These micro-inconsistencies compound into a fragmented user experience that erodes trust in the product.

Design tokens solve this by externalizing design decisions into a shared, version-controlled format. Instead of hardcoding #1D6EEB throughout your stylesheets, you reference var(--color-primary). When the brand color changes, you update one value and every surface reflects the change instantly.

Design tokens are not just about convenience. They encode the design intent behind every visual decision, making it possible for teams to reason about why a value exists, not just what it is.

The benefits extend beyond consistency. Tokens enable automated testing of visual properties, support dark mode and high-contrast themes through aliasing, and allow non-technical stakeholders to understand and contribute to the design language through a readable vocabulary.

The three-layer architecture

The most resilient token architectures use three distinct layers, each with a clear purpose. This separation of concerns mirrors well-known software patterns and makes it straightforward to modify one aspect of the system without breaking another.

Foundation tokens

Foundation tokens are raw, primitive values with no semantic meaning. They represent the complete palette of options available to the system. Think of them as your design vocabulary: every possible color, every spacing increment, every shadow definition.

/* Foundation tokens — raw values */
--blue-500: #1D6EEB;
--blue-600: #1B69C2;
--gray-100: #F2F4F7;
--gray-900: #101828;
--space-4:  16px;
--space-6:  24px;

Foundation tokens should never be referenced directly in component styles. They exist solely to provide the raw material that brand and semantic tokens draw from. This constraint is critical: it means you can completely swap out a foundation palette without touching any component code.

Brand tokens

Brand tokens map foundation values to product-specific identities. They answer the question: "Which foundation value represents our primary brand color?" This layer is where multi-brand and white-label scenarios are handled.

Semantic tokens

Semantic tokens are the tokens that components actually consume. They describe the purpose of a value, not its visual appearance. --color-error is semantic; --red-500 is not. This distinction is what makes theming possible: in dark mode, --color-error might resolve to a lighter red for legibility, while --red-500 remains unchanged.

  1. Define the intent: what does the component need? (e.g., a surface color, a text color, an interactive state)
  2. Map to brand tokens: connect the intent to a brand-level decision
  3. Override per theme: dark mode, high contrast, and brand variants each provide their own mappings
  4. Consume in components: every var() reference in CSS uses a semantic token

Implementation strategies

Choosing the right format and tooling for your tokens depends on your tech stack, team size, and delivery requirements. Here are the approaches we have seen work well at different scales.

CSS custom properties

For web-first teams, CSS custom properties provide native token support with zero build-step overhead. They cascade naturally, can be scoped to components, and support runtime theming through class-based overrides. The Morpheme design system uses this approach with a root-level declaration block:

:root {
  --color-primary:       #1D6EEB;
  --color-primary-light: #EFF8FF;
  --color-error:         #F04438;
  --shadow-md: 0 4px 8px -2px rgba(16,24,40,0.10),
               0 2px 4px -2px rgba(16,24,40,0.06);
}

.theme-dark {
  --color-primary:       #60A5FA;
  --color-primary-light: #1D2939;
  --color-error:         #FCA5A5;
}

The advantage here is simplicity and browser-native performance. The tradeoff is that CSS custom properties are string-based, which means you lose type safety and cannot perform compile-time validation of token references.

Token transformation pipelines

For multi-platform teams (web, iOS, Android), tools like Style Dictionary or Theo allow you to define tokens in a canonical JSON format and transform them into platform-specific outputs: CSS variables, Swift enums, Kotlin objects, or XML resources. This approach adds build complexity but ensures cross-platform consistency from a single source.

The best token architecture is the one your team will actually maintain. Start with the simplest approach that meets your current needs, and add transformation layers only when multi-platform delivery demands it.

Measuring adoption

A token architecture is only valuable if teams actually use it. Without measurement, you are building infrastructure on faith. Here are the metrics that matter most:

We recommend running automated linting rules that flag raw hex values, pixel literals, and font-family strings that should be token references. These checks can run in CI pipelines and pull request reviews, catching regressions before they reach production.

Token adoption is a cultural challenge as much as a technical one. Invest in onboarding documentation, pair programming sessions with early adopters, and a responsive support channel. The fastest path to adoption is making the right thing the easy thing: when using a token is simpler than hardcoding a value, teams will adopt naturally.