Learn the concept
Component Architecture at Scale
A scalable design system uses design tokens for themeable foundations, a tiered component hierarchy (primitives, patterns, templates), semver versioning with a clear breaking change policy, Storybook for documentation, and an RFC governance process for multi-team contributions.
A design system is the single source of truth for UI across an organization. At scale, it serves dozens of teams and hundreds of engineers. Getting the architecture right is critical because migration costs grow exponentially with adoption.
Functional Requirements:
Non-Functional Requirements:
Design tokens are the atomic values of your design system: colors, spacing, typography, shadows, border radii, and motion. They are the contract between design and engineering.
Token hierarchy:
color-blue-500: #3B82F6)color-primary: var(--color-blue-500))button-bg: var(--color-primary))Why CSS custom properties?
Organize components in three tiers:
Low-level, unstyled building blocks:
These have zero opinions about layout or content — they only handle behavior, accessibility, and token consumption.
Composed from primitives with opinionated layouts:
Page-level compositions for common layouts:
Teams consume the tier they need: use primitives for custom UIs, patterns for standard features, templates for rapid page building.
Follow strict semver with a clear policy:
Breaking change policy:
Storybook is the industry standard for component documentation:
Deploy Storybook to a URL like design.company.com so designers and PMs can reference it.
Publish as an npm package from a monorepo (Turborepo or Nx):
@company/design-tokens → CSS variables + JSON
@company/primitives → Tier 1 components
@company/patterns → Tier 2 components
@company/theme → ThemeProvider + presets
Split packages allow teams to import only what they need. Each package is individually versioned and tree-shakeable.
Tree-shaking setup:
sideEffects: false in package.jsonpreserveModules: true in the bundler configSupport multiple themes (light, dark, brand variants) via a ThemeProvider that sets CSS custom properties on a root element:
For multi-team adoption, you need a contribution process:
This prevents the design system from becoming a bottleneck while maintaining quality.
// tokens/colors.ts — Global tokens
export const colors = {
blue: {
50: '#EFF6FF',
100: '#DBEAFE',
500: '#3B82F6',
600: '#2563EB',
700: '#1D4ED8',
900: '#1E3A8A',
},
gray: {
50: '#F9FAFB',
100: '#F3F4F6',
200: '#E5E7EB',
700: '#374151',
800: '#1F2937',
900: '#111827',
},
} as const;
// tokens/themes.ts — Semantic tokens per theme
export interface Theme {
'color-bg-primary': string;
'color-bg-secondary': string;
'color-text-primary': string;
'color-text-secondary': string;
'color-border': string;
'color-accent': string;
'color-accent-hover': string;
'shadow-sm': string;
'shadow-md': string;
'radius-sm': string;
'radius-md': string;
'radius-lg': string;
'spacing-xs': string;
'spacing-sm': string;
'spacing-md': string;
'spacing-lg': string;
}
export const lightTheme: Theme = {
'color-bg-primary': colors.gray[50],
'color-bg-secondary': '#FFFFFF',
'color-text-primary': colors.gray[900],
'color-text-secondary': colors.gray[700],
'color-border': colors.gray[200],
'color-accent': colors.blue[600],
'color-accent-hover': colors.blue[700],
'shadow-sm': '0 1px 2px rgba(0,0,0,0.05)',
'shadow-md': '0 4px 6px rgba(0,0,0,0.07)',
'radius-sm': '4px',
'radius-md': '8px',
'radius-lg': '12px',
'spacing-xs': '4px',
'spacing-sm': '8px',
'spacing-md': '16px',
'spacing-lg': '24px',
};
export const darkTheme: Theme = {
'color-bg-primary': colors.gray[900],
'color-bg-secondary': colors.gray[800],
'color-text-primary': colors.gray[50],
'color-text-secondary': colors.gray[200],
'color-border': colors.gray[700],
'color-accent': colors.blue[500],
'color-accent-hover': colors.blue[600],
'shadow-sm': '0 1px 2px rgba(0,0,0,0.3)',
'shadow-md': '0 4px 6px rgba(0,0,0,0.4)',
'radius-sm': '4px',
'radius-md': '8px',
'radius-lg': '12px',
'spacing-xs': '4px',
'spacing-sm': '8px',
'spacing-md': '16px',
'spacing-lg': '24px',
};
// Apply theme as CSS custom properties
export function applyTheme(theme: Theme, root: HTMLElement = document.documentElement) {
for (const [key, value] of Object.entries(theme)) {
root.style.setProperty(`--${key}`, value);
}
}Organizations with multiple products (e.g., Atlassian with Jira, Confluence, Trello) use a shared design system to ensure visual consistency, reduce design debt, and allow engineers to move between teams without relearning UI patterns.
SaaS companies that offer white-label products use token-based theming to allow each customer to apply their own branding (colors, logos, typography) without changing the underlying component code.
Design tokens exported to Figma variables and CSS custom properties simultaneously create a single source of truth that eliminates translation errors between design mocks and implemented components.
Build an interactive playground where users can adjust design tokens (colors, spacing, border radius) via sliders and color pickers, seeing a set of components update in real time. Export the custom theme as CSS or JSON.
Create a small component library (Button, Input, Card, Badge) with design tokens, TypeScript types, Storybook stories with controls, and automated accessibility audits via axe-core. Publish as an npm package.
Polaris design system provides tokens, components, and patterns for thousands of Shopify apps to maintain consistency across the Shopify ecosystem, with public governance and contribution guidelines
Atlassian Design System serves Jira, Confluence, Bitbucket, and Trello with shared tokens and components, using a multi-tier token system (global, semantic, component) for scalable theming