Build a Token Pipeline with Style Dictionary

Transform design tokens from JSON to CSS, iOS, Android in one command. One source of truth, every platform covered.

What you will need

Node.js

Version 20 or later. This runs Style Dictionary and the npm scripts you will set up.

Open
A terminal

Terminal on Mac, the built-in terminal in VS Code, or Windows Terminal. You will run a few install and build commands.

Design tokens in JSON

Either an existing token file exported from Figma or Tokens Studio, or a willingness to create one. The scaffold in step 1 generates an example for you.

30 minutes

Time to install, scaffold, configure, and run your first multi-platform build.

Token build pipeline
  1. 01

    JSON tokens

    Design decisions in a single source of truth

  2. 02

    Transforms

    Style Dictionary applies naming, format, and value rules

  3. 03

    CSS

    Custom properties for web

  4. 04

    iOS + Android

    Swift enums and XML resources

Why This Matters for Your Design System

I maintained four separate token files for two years. One for CSS. One for iOS. One for Android. One “source of truth” in Figma that was never actually true because someone always forgot to update one of the other three.

Style Dictionary killed that entire problem in a single afternoon. You define your tokens once, in one JSON file, and it generates every platform format on command. This workflow shows you how to set it up so you never manually translate a hex value to a UIColor again.


Step 1: Install Style Dictionary

Open your terminal and create a new project folder. Then install Style Dictionary as a development dependency.

mkdir my-design-tokens
cd my-design-tokens
npm init -y
npm install -D style-dictionary

Alternatively, you can use Style Dictionary’s built-in scaffolding to generate a starter project with example tokens:

npx style-dictionary init basic

This creates a complete working example with token files, a configuration, and build outputs for multiple platforms.

Why this step matters: Starting with the scaffolded project gives you a working reference. You can see exactly what inputs produce which outputs before you start customizing anything.


Step 2: Organize Your Token Files

Style Dictionary reads tokens from JSON files. The structure is flexible, but a clear hierarchy keeps things manageable as your system grows.

Create a tokens/ folder with this structure:

tokens/
  color/
    base.json
    semantic.json
  spacing/
    base.json
  typography/
    base.json

Here is an example tokens/color/base.json:

{
  "color": {
    "base": {
      "blue": {
        "100": { "$value": "#DBEAFE" },
        "500": { "$value": "#3B82F6" },
        "900": { "$value": "#1E3A8A" }
      },
      "gray": {
        "100": { "$value": "#F3F4F6" },
        "500": { "$value": "#6B7280" },
        "900": { "$value": "#111827" }
      }
    }
  }
}

And an example tokens/color/semantic.json that references base values:

{
  "color": {
    "background": {
      "primary": { "$value": "{color.base.gray.100}" },
      "inverse": { "$value": "{color.base.gray.900}" }
    },
    "action": {
      "primary": { "$value": "{color.base.blue.500}" }
    }
  }
}

Why this step matters: Splitting tokens across files makes them easier to find and maintain. Style Dictionary deep-merges all files automatically, so you can organize by category without worrying about how they connect. The reference syntax ({color.base.blue.500}) means changing a base value automatically propagates to every semantic token that uses it.


Step 3: Create the Configuration File

The configuration tells Style Dictionary where to find your tokens and what to output. Create a config.json in your project root:

{
  "source": ["tokens/**/*.json"],
  "platforms": {
    "css": {
      "transformGroup": "css",
      "buildPath": "build/css/",
      "files": [
        {
          "destination": "variables.css",
          "format": "css/variables"
        }
      ]
    },
    "ios": {
      "transformGroup": "ios-swift",
      "buildPath": "build/ios/",
      "files": [
        {
          "destination": "DesignTokens.swift",
          "format": "ios-swift/class.swift",
          "className": "DesignTokens"
        }
      ]
    },
    "android": {
      "transformGroup": "android",
      "buildPath": "build/android/",
      "files": [
        {
          "destination": "colors.xml",
          "format": "android/resources",
          "resourceType": "color",
          "filter": {
            "type": "color"
          }
        }
      ]
    }
  }
}

Why this step matters: Each platform block defines a transform group (which converts values to the right format), a build path (where files go), and output files. The transformGroup is doing the heavy lifting. For CSS, it converts colors to hex strings. For iOS, it converts them to UIColor calls. For Android, it wraps them in XML resource tags. You write tokens once. Style Dictionary handles the translation.


Step 4: Run the Build

Add a build script to your package.json:

{
  "scripts": {
    "build:tokens": "style-dictionary build"
  }
}

Then run it:

npm run build:tokens

You should see output like this:

css
  ✔ build/css/variables.css

ios
  ✔ build/ios/DesignTokens.swift

android
  ✔ build/android/colors.xml

Open the generated files to verify the output. Your CSS file should look something like:

:root {
  --color-base-blue-100: #DBEAFE;
  --color-base-blue-500: #3B82F6;
  --color-base-blue-900: #1E3A8A;
  --color-background-primary: #F3F4F6;
  --color-background-inverse: #111827;
  --color-action-primary: #3B82F6;
}

Why this step matters: This is the moment where everything clicks. One command, three platform outputs, all consistent. If you change blue.500 from #3B82F6 to #2563EB, every platform file updates on the next build. No searching, no find-and-replace.


Step 5: Add Dark Mode Support

Most design systems need multiple themes. Style Dictionary handles this through separate source files and platform configurations.

Create tokens/color/dark.json:

{
  "color": {
    "background": {
      "primary": { "$value": "{color.base.gray.900}" },
      "inverse": { "$value": "{color.base.gray.100}" }
    },
    "action": {
      "primary": { "$value": "{color.base.blue.500}" }
    }
  }
}

Then add a dark theme platform to your config:

{
  "css-dark": {
    "transformGroup": "css",
    "buildPath": "build/css/",
    "files": [
      {
        "destination": "variables-dark.css",
        "format": "css/variables",
        "options": {
          "selector": "[data-theme='dark']"
        }
      }
    ],
    "source": ["tokens/color/base.json", "tokens/color/dark.json"]
  }
}

Why this step matters: Theme support is where token pipelines prove their worth. Without a pipeline, maintaining light and dark themes means manually updating two sets of values in every platform. With Style Dictionary, you define the overrides once and the build handles the rest.


Step 6: Integrate with Your Workflow

Now that your pipeline works locally, connect it to the rest of your workflow.

The full loop looks like this: designer updates a token in Figma, Tokens Studio pushes the JSON to GitHub, GitHub Actions runs Style Dictionary, and the built files are published as a package. End to end, no manual steps.

Why this step matters: A build tool running on your laptop is useful. A build tool running automatically in a pipeline is transformational. The goal is to remove yourself from the publishing process entirely so you can focus on design decisions instead of file management.


What You Get

  • One source of truth. All platform outputs derive from the same JSON tokens.
  • Platform-native formats. CSS custom properties, Swift constants, Android XML resources, Kotlin Compose objects, and more.
  • Automatic reference resolution. Semantic tokens that reference primitives are resolved at build time.
  • Extensibility. Style Dictionary supports custom transforms, formats, and filters when the built-in options are not enough.

Common Pitfalls

  • Circular references. If Token A references Token B and Token B references Token A, the build will fail. Keep your reference chain one-directional: primitives to semantic, never the reverse.
  • Missing $value key. Style Dictionary v4 uses the DTCG format with $value. Older tutorials may show value without the dollar sign. Check which version you are using.
  • Forgetting to rebuild. Changes to token JSON files are not reflected until you run the build command again. Automate this with a file watcher or CI pipeline.

Exercise

Build a working pipeline from one hex value to three platforms

30 min
  1. Scaffold a minimal pipeline with one primitive and one semantic token

    Create a folder. Run npm init -y && npm install -D style-dictionary. Add tokens/color/base.json with one color (color.base.blue.500 = #3B82F6). Add tokens/color/semantic.json with one reference (color.action.primary = {color.base.blue.500}). Copy the config.json from Step 3 of this guide with all three platforms (css, ios, android). Run npx style-dictionary build. Verify three files appear under build/.

    • build/css/variables.css contains both --color-base-blue-500 and --color-action-primary
    • build/ios/DesignTokens.swift compiles if you paste it into a Swift Playground
    • build/android/colors.xml contains the resolved hex value, not a token reference
    • All three files were generated from a single npx style-dictionary build command
  2. Change one primitive, watch three platforms update

    Change color.base.blue.500 from #3B82F6 to #2563EB in tokens/color/base.json. Run the build again. Open all three output files. Confirm the new hex appears in every one, including the semantic token that referenced it. This is the moment where the pipeline proves itself. Without Style Dictionary, that change is one find-and-replace per platform. With it, it is one save.

    • The new hex #2563EB appears in all three output files
    • color.action.primary still references the updated value (you did not have to edit the semantic token)
    • You can now describe to a teammate in two sentences why this pattern beats maintaining separate token files per platform
    • You have a tiny repo you can copy and adapt for a real project tomorrow

Finished this lesson?

Mark it complete to track your progress through "Design System Automation".

Lesson
7 / 12
Progress
58%
Read time
30 min
Free to try Cancel anytime
The guides alone saved me a full day of work every sprint.
Senior Design Systems Lead
Enterprise SaaS
Pro
Full access to everything.
$39 /month
  • All guides, prompts, and templates
  • Starter kits and templates
  • New content every week
  • Priority support