On this page · sections
Design Token Pipeline
Design tokens are named design decisions stored as data — color, spacing, typography, radius — flowing to CSS variables, TypeScript, iOS Swift, and Android XML from a single source of truth.
| Layer | Example | Who consumes |
|---|---|---|
| Primitive | color.blue.600: #2563eb | Token authors only |
| Semantic | color.text.primary | Theme definitions |
| Component | button.primary.background | UI components |
| Output | --color-brand-primary | Apps via generated CSS |
Tokens & Style Dictionary
Definition
{
"color": {
"brand": {
"primary": { "value": "#2563eb", "type": "color" },
"secondary": { "value": "#64748b", "type": "color" }
}
},
"spacing": {
"md": { "value": "16px", "type": "dimension" }
}
}/* dist/css/variables.css — generated, never hand-edited */
:root {
--color-brand-primary: #2563eb;
--color-brand-secondary: #64748b;
--spacing-md: 16px;
}Style Dictionary transforms token JSON/YAML through a build step into platform files using formats and transforms.
// style-dictionary.config.js
module.exports = {
source: ['tokens/**/*.json'],
platforms: {
css: {
transformGroup: 'css',
buildPath: 'dist/css/',
files: [{ destination: 'variables.css', format: 'css/variables' }],
},
js: {
transformGroup: 'js',
buildPath: 'dist/js/',
files: [{ destination: 'tokens.js', format: 'javascript/es6' }],
},
},
};tokens/*.json → style-dictionary build → dist/css · dist/js · dist/ios · consumers import artifactsWithout a pipeline, Figma hex values get copy-pasted into React and Swift separately — drift within one sprint.
Tokens Studio for Figma exports JSON compatible with Style Dictionary. Tailwind theme can consume generated token output.
Interview: Tokens are source data; CSS/Swift are build output — never edit generated files.
Token Taxonomy
Definition
- Primitive tokens — raw values —
color.blue.600: #2563eb,spacing.4: 16px - Semantic tokens — map intent —
color.text.primaryreferences primitive - Component tokens — scope to UI parts —
button.primary.backgroundreferences semantic
{
"color": {
"blue": { "600": { "value": "#2563eb", "type": "color" } },
"text": {
"primary": { "value": "{color.slate.900}", "type": "color" }
},
"action": {
"primary": { "value": "{color.blue.600}", "type": "color" }
}
}
}export function Button() {
return (
<button
style={{
background: 'var(--button-primary-background)',
color: 'var(--button-primary-text)',
}}
>
Submit
</button>
);
}Components consume semantic or component tokens only — never color.blue.600 in a Button.
Primitive → Semantic → Component → React var(--button-primary-background)
Dark theme: semantic text.primary remaps to different primitive — components unchangedReference syntax: {color.blue.600} in JSON value field. Max depth primitive → semantic → component (3 hops); avoid cycles.
Interview: UI code uses semantic/component tokens — primitives are for token authors and theme definitions.
Multi-Platform Output
Definition
One token source, multiple platforms in config:
module.exports = {
source: ['tokens/**/*.json'],
platforms: {
css: {
transformGroup: 'css',
buildPath: 'dist/css/',
files: [{
destination: 'variables.css',
format: 'css/variables',
options: { outputReferences: true },
}],
},
js: {
transformGroup: 'js',
buildPath: 'dist/js/',
files: [{ destination: 'tokens.mjs', format: 'javascript/esm' }],
},
ios: {
transformGroup: 'ios',
buildPath: 'dist/ios/',
files: [{ destination: 'Colors.swift', format: 'ios/swift/class.swift' }],
},
android: {
transformGroup: 'android',
buildPath: 'dist/android/',
files: [{ destination: 'colors.xml', format: 'android/colors' }],
},
},
};/* outputReferences: true — shows alias chain */
:root {
--color-text-primary: var(--color-slate-900);
--color-slate-900: #0f172a;
}Custom transforms convert name case (camelCase → kebab → Swift). Custom formats control file templates.
Tailwind: extend theme from generated JS — tokens are source, Tailwind is one web consumer.
Composite typography tokens bundle fontFamily, fontSize, lineHeight — custom format outputs shorthand CSS.
Interview: One JSON source, N platform outputs — change token once, all platforms update on next build.
CI Integration & Versioning
Definition
{
"scripts": {
"tokens:build": "style-dictionary build",
"tokens:ci": "style-dictionary build && git diff --exit-code dist/"
}
}# CI — fail if generated output not committed
- run: pnpm tokens:build
- run: git diff --exit-code packages/tokens/dist/Pipeline:
Designer updates Figma → export JSON → PR → CI builds tokens → diff check → publish @company/tokens package- Generated artifacts committed or built in CI before app build — pick one, document it
- Semver on token package — breaking renames are major bumps
- Deprecation — alias old token names for one release before removal
- Visual regression — Chromatic/Percy on components after token changes
Apps depend on @company/tokens semver range — not relative Figma hex. Lock token version in monorepo with Changesets.
Breaking change: rename color.text.primary → coordinate codemod across all consuming apps in same release train.
Interview: CI diff check on
dist/catches “forgot to rebuild tokens” PRs.
Design-System Governance
Definition
Staff concerns at scale:
- Token RFC process — propose new semantic token with use case, not ad-hoc primitives in product apps
- Naming convention —
category.role.variant(e.g.color.text.primary) - Forbidden patterns — no raw hex in product code; lint with stylelint/custom ESLint rule
- Theme switching — CSS
[data-theme="dark"]remaps semantic references, not component rewrites - Cross-platform parity — iOS/Android get same semantic names, platform-specific transforms
Governance flow:
design proposes → token RFC → design-system team approves → CI build → semver publish → app bumps depFigma ↔ code sync: Tokens Studio plugin → JSON in repo → Style Dictionary → package. Designers don’t paste hex into Slack.
Document token deprecation in CHANGELOG. Provide migration map: color.text.default → color.text.primary.
Platform team owns token package, build config, and lint rules. Product teams consume — don’t fork token JSON.
Accessibility: contrast ratios validated at semantic layer — color.text.primary on color.bg.primary must pass WCAG in both themes.
Interview: Governance prevents 50 teams inventing slightly different blues — semantic layer is the contract.
Senior Interview Summary
Tokens
Named design decisions as data. Single source of truth for all platforms.
Style Dictionary
Transforms JSON → CSS/JS/Swift/Android. Custom transforms and formats per platform.
Taxonomy
Primitive → semantic → component. UI consumes semantic/component only.
CI
Build tokens in CI. Diff check on generated output. Semver on token package.
Governance
RFC process, naming conventions, lint against raw hex, deprecation aliases.
Best mental model
Figma JSON → source of truth (via Tokens Studio)
Style Dict → build engine
dist/ → generated artifacts (never hand-edit)
Apps → import package, use CSS variablesPractical rules
Product code → var(--semantic-token), never #2563eb
Dark mode → remap semantics, not components
Breaking rename → major semver + codemod
Token PR → rebuild dist + visual regressionWhat to say in interviews
Explain three token layers, how Style Dictionary multi-platform output works, CI diff check on generated files, and governance preventing primitive palette sprawl in product apps.