Case Study
Figma Design Token Rewrite
A ground-up rebuild of a global financial services Figma design token architecture — migrating two enterprise-scale libraries from a bloated, inconsistent legacy system to a clean, variable-driven semantic token model aligned with production CSS and W3C standards. The project covered two enterprise design system libraries simultaneously, reducing token count by 56% while increasing coverage and consistency.
Overview
Two enterprise libraries powering the same global financial services platform were rebuilt in parallel, replacing flat primitive dumps and broken bindings with a semantic alias layer and a generated CSS export aligned to W3C DTCG.
The problem
The existing legacy token libraries were the product of years of uncoordinated growth. Tokens used Title Case naming with emoji prefixes, had no codeSyntax.WEB values (meaning Figma's developer tools returned nothing useful), and were structured as flat primitive dumps with no semantic layer. Components were bound directly to color primitives, bypassing any semantic aliasing — so a brand color change required hundreds of manual rebinds across thousands of nodes.
By the time the audit ran, the two libraries had accumulated 262 and 268 tokens respectively — nearly 3x the industry standard for an enterprise system of this scale. 6,209 variable bindings in one library were outright broken, pointing to deleted primitives with no path to resolution. The system had 12 external library dependencies in one file and 6 in the other, creating circular reference risks. Production CSS had two broken custom properties shipping to users — broken since a previous refactor that was never completed.
What was done
The migration was executed in phases using a combination of custom MCP-driven Figma scripts and structured analysis.
Phase 1
Audit and mapping
Queried both libraries end-to-end via Figma MCP to produce a complete inventory of every variable, its collection, naming format, alias chain, codeSyntax.WEB status, and binding count. Cross-referenced against production CSS to identify what was actually in use versus what was dead weight.
Phase 2
Naming and codeSyntax
Renamed 168 variables from Title Case to lowercase kebab-case using slash-separated hierarchy (color/action/button-default, spacing/md, radius/pill). Set codeSyntax.WEB on all 179 variables, bringing coverage from 0% to 100%. All variables now return usable CSS custom property names from Figma's developer tools and MCP.
Phase 3
Semantic layer
Established a clean two-tier architecture — semantic Tokens collection aliasing into typed Primitives. Designers work only with semantic tokens (what a color is for, not what it is). Primitives are an implementation detail. Created 11 missing variables (5 colors, 6 radius tokens) to close gaps between the Figma system and production CSS needs.
Phase 4
Token consolidation
Reduced both libraries from ~265 tokens to 116 — the number that maps precisely to production CSS usage. Eliminated 3x spacing token bloat (30 → 10 t-shirt sizes), 6x typography token bloat (77 → 15 semantic typography tokens), and consolidated redundant color scales. Removed all 18 external library dependencies.
Phase 5
Binding repair
Resolved 6,209 broken variable bindings by building an automated rebinding script that mapped deleted primitive IDs to their correct Tokens collection replacements. What would have taken 40–80 hours of manual Figma work took under 4 hours to script and 30 minutes to run.
Phase 6
CSS export pipeline
Built a Node.js script (generate-tokens-css.mjs) that pulls the Tokens collection via the Figma Variables API, resolves all alias chains to raw values, and writes three output formats: CSS custom properties (:root { ... }), a JSON token map for tooling, and a W3C DTCG-compliant JSON file for cross-platform use. Achieved 96.3% parity between the Figma export and the live production CSS theme.
Numbers
Before
- 262 tokens (Library A), 268 tokens (Library B)
- 0% codeSyntax.WEB coverage
- 168 variables in Title Case with no CSS output
- 6,209 broken variable bindings
- 18 external library dependencies across both files
- 0 semantic alias layer
- 2 broken CSS custom properties in production
After
- 116 tokens in each library (56% reduction)
- 100% codeSyntax.WEB coverage — every variable returns a usable CSS name
- Clean two-tier architecture: Tokens (semantic) → Primitives → RGB
- 0 broken bindings
- 0 external dependencies
- 96.3% Figma-to-production CSS parity
- Token export pipeline producing CSS, JSON, and W3C DTCG outputs from a single Figma source
Project artifacts
Token outputs generated from the same source include CSS custom properties and a W3C token JSON map. The previews below show representative values from that artifact set.
Color tokens
Action
- #1d2550
--color-action-button-default
- #302b25
--color-action-button-hover
- #302b25
--color-action-button-pressed
- #878787
--color-action-button-inactive
- #ffffff
--color-action-button-label
- #302b25
--color-action-link-default
- #641ee0
--color-action-link-hover
- #813684
--color-action-link-visited
Alert
- #cf0000
--color-alert-error-text
- #ffeaeb
--color-alert-error-bg
- #fff7e6
--color-alert-warning-bg
- #e3f5e1
--color-alert-success-bg
- #c7deff
--color-alert-info-bg
- #fdc828
--color-alert-highlight
Surface
- #ffffff
--color-surface-default
- #f2f2f2
--color-surface-subtle
- #1d2550
--color-surface-hero
- #fdc828
--color-surface-focus
Text
- #000000
--color-text-black
- #302b25
--color-text-on-light
- #6b6b6b
--color-text-muted
- #ffffff
--color-text-on-dark
Border
- #cfcfcf
--color-border-divider-light
- #ababab
--color-border-divider-medium
- #fdc828
--color-border-focus
Control
- #0061f4
--color-control-active
- #cf0000
--color-control-error
- #6b6b6b
--color-control-inactive
- #ffffff
--color-control-surface-primary
- #fafafa
--color-control-surface-secondary
Input
- #0061f4
--color-input-focus
- #302b25
--color-input-hover
- #0d7406
--color-input-success
- #c51321
--color-input-error
Accent
- #1d2550
--color-accent-night-blue
- #187ac9
--color-accent-sky-blue
- #278904
--color-accent-grass-green
- #cc1ad4
--color-accent-hot-pink
- #e7ff00
--color-accent-yellow
Spacing tokens
- --spacing-tn4px
- --spacing-xs8px
- --spacing-sm12px
- --spacing-md16px
- --spacing-lg24px
- --spacing-xl32px
Radius tokens
- --radius-card6px
- --radius-component8px
- --radius-pill80px
Typography tokens
--typography-display-lg · 72px
Display
--typography-display-sm · 48px
Display
--typography-heading-xl · 40px
Heading
--typography-heading-lg · 36px
Heading
--typography-heading-md · 32px
Heading
--typography-heading-sm · 26px
Heading
--typography-body-xl · 22px
The quick brown fox jumps over the lazy dog
--typography-body-lg · 20px
The quick brown fox jumps over the lazy dog
--typography-body-md · 18px
The quick brown fox jumps over the lazy dog
--typography-body-sm · 14px
The quick brown fox jumps over the lazy dog
--typography-weight-light
Weight 300
--typography-weight-regular
Weight 400
--typography-weight-medium
Weight 500
--typography-weight-semi-bold
Weight 600
--typography-weight-bold
Weight 700
Business value
Figma as the single source of truth
Previously, a designer changing a brand color in Figma had no reliable path to production — the CSS ignored it, the token names meant nothing to engineers, and the developer inspect panel returned empty. Now a token change in Figma flows to generated CSS in minutes.
Intent is encoded, not just values
The semantic layer means a developer consuming --color-action-button-default knows exactly what they're styling — and knows it will never be an arbitrary hex. Brand changes propagate through the alias chain automatically rather than requiring a file-wide search and replace.
A learnable system
The reduction from ~265 to 116 tokens makes the system learnable. New designers and engineers can understand the full token vocabulary in an afternoon rather than inheriting a system that nobody fully understood.