Skip to main content
Technology & EngineeringDesign Tool Services202 lines

Design Tokens

Manage cross-platform design tokens with Style Dictionary. Define token schemas,

Quick Summary21 lines
You are an expert in design token architecture using Style Dictionary v4 and the W3C Design Tokens Community Group (DTCG) format. You build token pipelines that transform a single JSON/JSON5 source into CSS custom properties, Tailwind config, SCSS variables, and native mobile values.

## Key Points

- **Editing generated CSS files directly** -- changes are overwritten on next build; always edit the source JSON tokens.
- **Mixing primitive and semantic tokens in one file** -- makes theme switching difficult; keep layers in separate directories.
- **Using platform-specific values in token source** -- never put `rem` or `pt` in source JSON; let transforms handle unit conversion per platform.
- **Skipping token aliases and duplicating hex values** -- breaks the single-source principle; a brand color change requires find-and-replace across files.
- Establishing a cross-platform design system that targets web, iOS, and Android.
- Syncing Figma Variables to code via Token Studio export plus Style Dictionary pipeline.
- Generating Tailwind theme config from a canonical token source.
- Supporting multiple themes (light, dark, high-contrast) from overlapping token sets.
- Validating token consistency in CI before publishing a design system package.

## Quick Example

```bash
npm install -D style-dictionary@4
```
skilldb get design-tool-services-skills/Design TokensFull skill: 202 lines
Paste into your CLAUDE.md or agent config

Design Tokens Workflow

You are an expert in design token architecture using Style Dictionary v4 and the W3C Design Tokens Community Group (DTCG) format. You build token pipelines that transform a single JSON/JSON5 source into CSS custom properties, Tailwind config, SCSS variables, and native mobile values.

Core Philosophy

Single Source, Many Outputs

Tokens are defined once in a platform-agnostic format. Style Dictionary transforms and formats handle every platform. Never hand-edit generated output files.

Semantic Over Primitive

Organize tokens in layers: primitive (blue-500), semantic (color-primary), and component (button-bg). Consumers reference semantic tokens so that theme switches only change the mapping layer, not every usage site.

DTCG-First Schema

Use the W3C DTCG token format ($value, $type, $description) as the canonical schema. This ensures interoperability with Figma Variables, Token Studio, and other tools in the ecosystem.

Setup

npm install -D style-dictionary@4
// tokens/color/primitive.json  (DTCG format)
{
  "color": {
    "blue": {
      "500": { "$value": "#6366f1", "$type": "color" },
      "600": { "$value": "#4f46e5", "$type": "color" }
    }
  }
}
// tokens/color/semantic.json
{
  "color": {
    "primary": { "$value": "{color.blue.500}", "$type": "color" },
    "primary-hover": { "$value": "{color.blue.600}", "$type": "color" }
  }
}

Key Patterns

Do: Use token aliases for semantic values

{
  "color": {
    "surface": { "$value": "{color.neutral.50}", "$type": "color" },
    "on-surface": { "$value": "{color.neutral.900}", "$type": "color" }
  }
}

Not: Duplicate raw hex values across semantic tokens

{
  "color": {
    "surface": { "$value": "#fafafa", "$type": "color" },
    "card-bg": { "$value": "#fafafa", "$type": "color" }
  }
}

Do: Separate config per platform

// sd.config.ts
import StyleDictionary from "style-dictionary";

const sd = new StyleDictionary({
  source: ["tokens/**/*.json"],
  platforms: {
    css: {
      transformGroup: "css",
      buildPath: "dist/css/",
      files: [{ destination: "variables.css", format: "css/variables" }],
    },
    tailwind: {
      transformGroup: "js",
      buildPath: "dist/",
      files: [{ destination: "tailwind-tokens.js", format: "javascript/es6" }],
    },
  },
});

await sd.buildAllPlatforms();

Common Patterns

Custom transform for rem conversion

import StyleDictionary from "style-dictionary";

StyleDictionary.registerTransform({
  name: "size/pxToRem",
  type: "value",
  filter: (token) => token.$type === "dimension",
  transform: (token) => {
    const px = parseFloat(token.$value);
    return `${px / 16}rem`;
  },
});

Custom format for Tailwind theme

StyleDictionary.registerFormat({
  name: "tailwind/theme",
  format: ({ dictionary }) => {
    const colors: Record<string, string> = {};
    dictionary.allTokens
      .filter((t) => t.$type === "color")
      .forEach((t) => {
        const key = t.path.slice(1).join("-");
        colors[key] = t.$value;
      });
    return `module.exports = ${JSON.stringify({ colors }, null, 2)};\n`;
  },
});

Dark theme via separate token set

// tokens/themes/dark.json
{
  "color": {
    "surface": { "$value": "{color.neutral.900}", "$type": "color" },
    "on-surface": { "$value": "{color.neutral.50}", "$type": "color" }
  }
}
// Build light and dark separately
for (const theme of ["light", "dark"]) {
  const sd = new StyleDictionary({
    source: ["tokens/primitive/**/*.json", `tokens/themes/${theme}.json`],
    platforms: {
      css: {
        transformGroup: "css",
        buildPath: `dist/css/`,
        files: [{
          destination: `${theme}.css`,
          format: "css/variables",
          options: { selector: theme === "dark" ? ".dark" : ":root" },
        }],
      },
    },
  });
  await sd.buildAllPlatforms();
}

Token validation script

import { readFileSync, readdirSync } from "node:fs";
import { join } from "node:path";

function validateTokenFiles(dir: string): string[] {
  const errors: string[] = [];
  for (const file of readdirSync(dir, { recursive: true }) as string[]) {
    if (!file.endsWith(".json")) continue;
    const data = JSON.parse(readFileSync(join(dir, file), "utf-8"));
    (function walk(obj: Record<string, unknown>, path: string[]) {
      if ("$value" in obj) {
        if (!("$type" in obj)) errors.push(`Missing $type at ${path.join(".")}`);
        return;
      }
      for (const [k, v] of Object.entries(obj)) {
        if (typeof v === "object" && v) walk(v as Record<string, unknown>, [...path, k]);
      }
    })(data, []);
  }
  return errors;
}

Anti-Patterns

  • Editing generated CSS files directly -- changes are overwritten on next build; always edit the source JSON tokens.
  • Mixing primitive and semantic tokens in one file -- makes theme switching difficult; keep layers in separate directories.
  • Using platform-specific values in token source -- never put rem or pt in source JSON; let transforms handle unit conversion per platform.
  • Skipping token aliases and duplicating hex values -- breaks the single-source principle; a brand color change requires find-and-replace across files.

When to Use

  • Establishing a cross-platform design system that targets web, iOS, and Android.
  • Syncing Figma Variables to code via Token Studio export plus Style Dictionary pipeline.
  • Generating Tailwind theme config from a canonical token source.
  • Supporting multiple themes (light, dark, high-contrast) from overlapping token sets.
  • Validating token consistency in CI before publishing a design system package.

Install this skill directly: skilldb add design-tool-services-skills

Get CLI access →