Build an end-to-end automated design token pipeline that exports tokens from Figma, transforms them with Style Dictionary, and generates platform-specific output for web, iOS, and Android.
Build an end-to-end automated design token pipeline that exports tokens from Figma, transforms them with Style Dictionary, and generates platform-specific output for web, iOS, and Android.
Tokens Studio (formerly Figma Tokens) is the de facto standard plugin for managing design tokens in Figma. It stores tokens as JSON in a structure that maps directly to Style Dictionary input. Configure your token sets with a clear three-tier hierarchy:
1// tokens/global.json — raw values
2{
3 "color": {
4 "blue": {
5 "100": { "value": "#EFF6FF", "type": "color" },
6 "500": { "value": "#3B82F6", "type": "color" },
7 "900": { "value": "#1E3A8A", "type": "color" }
8 }
9 },
10 "spacing": {
11 "1": { "value": "4", "type": "spacing" },
12 "4": { "value": "16", "type": "spacing" },
13 "8": { "value": "32", "type": "spacing" }
14 }
15}
16
17// tokens/semantic.json — references global, carries intent
18{
19 "color": {
20 "interactive": {
21 "primary": { "value": "{color.blue.500}", "type": "color" },
22 "primary-hover": { "value": "{color.blue.600}", "type": "color" }
23 },
24 "surface": {
25 "default": { "value": "{color.white}", "type": "color" },
26 "raised": { "value": "{color.gray.50}", "type": "color" }
27 }
28 }
29}Push tokens to a GitHub repository from Tokens Studio using its built-in GitHub sync. This creates a pull request with token changes, enabling review before the pipeline runs.
Style Dictionary transforms token JSON into platform-specific output. Configure custom transforms for your token conventions:
1// style-dictionary.config.mjs
2import StyleDictionary from 'style-dictionary';
3
4// Custom transform: convert px spacing to rem
5StyleDictionary.registerTransform({
6 name: 'size/pxToRem',
7 type: 'value',
8 matcher: (token) => token.type === 'spacing' || token.type === 'sizing',
9 transformer: (token) => `${parseFloat(token.value) / 16}rem`,
10});
11
12// Custom format: CSS custom properties with semantic grouping
13StyleDictionary.registerFormat({
14 name: 'css/semantic-variables',
15 formatter: ({ dictionary }) => {
16 const vars = dictionary.allTokens
17 .map(token => ` --${token.name}: ${token.value};`)
18 .join('\n');
19 return `:root {\n${vars}\n}`;
20 },
21});
22
23export default {
24 source: ['tokens/global.json', 'tokens/semantic.json'],
25 platforms: {
26 css: {
27 transformGroup: 'css',
28 transforms: ['attribute/cti', 'name/cti/kebab', 'size/pxToRem', 'color/css'],
29 buildPath: 'dist/tokens/',
30 files: [
31 { destination: 'tokens.css', format: 'css/semantic-variables' },
32 ],
33 },
34 },
35};A single Style Dictionary configuration generates tokens for all platforms, ensuring design-to-code parity across web, iOS, and Android:
1// Add iOS and Android platforms to the config
2export default {
3 source: ['tokens/global.json', 'tokens/semantic.json'],
4 platforms: {
5 // Web CSS
6 css: {
7 transformGroup: 'css',
8 buildPath: 'dist/web/',
9 files: [{ destination: 'tokens.css', format: 'css/variables' }],
10 },
11
12 // iOS Swift
13 ios: {
14 transformGroup: 'ios-swift',
15 buildPath: 'dist/ios/',
16 files: [
17 {
18 destination: 'DesignTokens.swift',
19 format: 'ios-swift/enum.swift',
20 className: 'DesignToken',
21 filter: (token) => token.type === 'color',
22 },
23 ],
24 },
25
26 // Android XML
27 android: {
28 transformGroup: 'android',
29 buildPath: 'dist/android/',
30 files: [
31 {
32 destination: 'tokens_color.xml',
33 format: 'android/colors',
34 filter: (token) => token.type === 'color',
35 },
36 {
37 destination: 'tokens_dimension.xml',
38 format: 'android/dimens',
39 filter: (token) => token.type === 'spacing',
40 },
41 ],
42 },
43 },
44};The generated outputs are committed to platform-specific SDKs (iOS CocoaPod, Android library) via the same CI pipeline, ensuring all platforms use the same token values simultaneously.
Trigger the token pipeline automatically when designers push token changes from Figma:
1# .github/workflows/tokens.yml
2name: Token Pipeline
3
4on:
5 push:
6 paths:
7 - 'tokens/**/*.json' # Only runs when token files change
8 workflow_dispatch: # Manual trigger for testing
9
10jobs:
11 build-tokens:
12 runs-on: ubuntu-latest
13 steps:
14 - uses: actions/checkout@v4
15
16 - name: Install dependencies
17 run: npm install style-dictionary
18
19 - name: Validate tokens
20 run: node scripts/validate-tokens.mjs
21
22 - name: Build tokens
23 run: node style-dictionary.config.mjs
24
25 - name: Verify contrast ratios
26 run: node scripts/verify-contrast.mjs
27
28 - name: Open PR with generated files
29 uses: peter-evans/create-pull-request@v5
30 with:
31 commit-message: 'chore(tokens): regenerate platform token files'
32 title: 'Tokens: Update from Figma sync'
33 body: 'Auto-generated from token changes. Review diff before merging.'
34 branch: 'tokens/auto-update'The pipeline opens a PR with the generated token diffs so engineers review the change before it ships. This prevents designers from accidentally shipping breaking token changes without a review gate.
The pipeline should reject incomplete or invalid token sets before generating output:
1// scripts/validate-tokens.mjs
2import { readFileSync } from 'fs';
3
4const global = JSON.parse(readFileSync('tokens/global.json', 'utf8'));
5const semantic = JSON.parse(readFileSync('tokens/semantic.json', 'utf8'));
6
7const REQUIRED_SEMANTIC_TOKENS = [
8 'color.interactive.primary',
9 'color.interactive.primary-hover',
10 'color.surface.default',
11 'color.surface.raised',
12 'color.text.primary',
13 'color.text.secondary',
14 'color.border.default',
15 'color.status.error',
16 'color.status.warning',
17 'color.status.success',
18];
19
20function getNestedValue(obj, path) {
21 return path.split('.').reduce((o, k) => o?.[k], obj);
22}
23
24const missing = REQUIRED_SEMANTIC_TOKENS.filter(
25 path => !getNestedValue(semantic, path)
26);
27
28if (missing.length > 0) {
29 console.error('Missing required semantic tokens:');
30 missing.forEach(t => console.error(' -', t));
31 process.exit(1);
32}
33
34console.log('All required tokens present. Validation passed.');This validation runs before Style Dictionary builds, ensuring you never ship an incomplete token set to consuming teams. Add dark mode completeness checks to verify every semantic token has a corresponding dark mode override.
Install Tokens Studio in Figma and connect it to your design system GitHub repository. Configure a basic Style Dictionary build that generates CSS custom properties from your Figma tokens and run it locally.
Your progress is saved in this browser, on this device only.