How to Convert DESIGN.md Design Tokens to W3C DTCG Format

TLDR: You can convert DESIGN.md design tokens to W3C DTCG format using the export --format dtcg CLI command or the DtcgEmitterHandler API, which maps colors, spacing, and typography into the 2025.10 DTCG schema.

The google-labs-code/design.md repository provides a complete pipeline for transforming markdown-based design systems into standardized token files. Whether you need a one-off export or a custom build integration, the project makes it straightforward to convert DESIGN.md design tokens to W3C DTCG format with full schema compliance.

CLI Export to W3C DTCG Format

The fastest way to generate a tokens.json file is through the CLI. In packages/cli/src/commands/export.ts, the command parses --format dtcg, reads the DESIGN.md input, runs the linter, and delegates to DtcgEmitterHandler. The handler returns { success: true, data: <tokens> }, and the CLI prints the result with two-space indentation via JSON.stringify(result.data, null, 2).

npx @google/design.md export --format dtcg DESIGN.md > tokens.json

Programmatic Conversion to W3C DTCG Format

For custom workflows, instantiate DtcgEmitterHandler from @google/design.md/linter/dtcg and pass it a DesignSystemState object. The handler lives in packages/cli/src/linter/dtcg/handler.ts and implements the DtcgEmitterSpec interface. Type definitions for the output structures, such as DtcgTokenFile and DtcgGroup, are declared in packages/cli/src/linter/dtcg/spec.ts, while packages/cli/src/linter/index.ts exposes the handlers for broader use.

Linting DESIGN.md and Emitting Tokens

Load the markdown, lint it, and call execute(state) to receive the DTCG object:

import { readFileSync } from 'fs';
import { lint } from '@google/design.md/linter';
import { DtcgEmitterHandler } from '@google/design.md/linter/dtcg';

// 1. Load a DESIGN.md file
const markdown = readFileSync('DESIGN.md', 'utf8');

// 2. Run the linter to obtain a DesignSystemState
const report = lint(markdown);

// 3. Convert to DTCG tokens
const handler = new DtcgEmitterHandler();
const result = handler.execute(report.designSystem);

if (result.success) {
  // 4. Write out the tokens.json file
  const json = JSON.stringify(result.data, null, 2);
  console.log(json);
} else {
  console.error('Export failed:', result.error);
}

Internal Mapping Methods

The execute method maps the internal DesignSystemState through dedicated helpers:

  • mapColors produces the color group
  • mapDimensionGroup produces the spacing and rounded groups
  • mapTypography produces the typography group

Value conversion is handled by colorToValue (sRGB arrays and hex strings), dimToValue ({ value, unit } objects), and typographyToValue (structured DTCG typography objects). An optional system description is added at the root as $description.

DTCG Output Structure and Schema

The emitted JSON declares the 2025.10 DTCG schema at https://www.designtokens.org/schemas/2025.10/format.json. Every group carries a $type field, and tokens expose their values under $value.

Colors, Dimensions, and Typography

  • Colors receive $type: "color" with colorSpace, components, and hex.
  • Spacing and rounded tokens receive $type: "dimension" with value and unit.
  • Typography tokens receive $type: "typography" with properties such as fontFamily and fontSize.
{
  "$schema": "https://www.designtokens.org/schemas/2025.10/format.json",
  "$description": "Heritage design system",
  "color": {
    "$type": "color",
    "primary": {
      "$value": {
        "colorSpace": "srgb",
        "components": [0.102, 0.110, 0.118],
        "hex": "#1a1c1e"
      }
    },
    "tertiary": {
      "$value": {
        "colorSpace": "srgb",
        "components": [0.724, 0.259, 0.180],
        "hex": "#b8422e"
      }
    }
  },
  "spacing": {
    "$type": "dimension",
    "sm": { "$value": { "value": 8, "unit": "px" } },
    "md": { "$value": { "value": 16, "unit": "px" } }
  },
  "typography": {
    "h1": {
      "$type": "typography",
      "$value": {
        "fontFamily": "Public Sans",
        "fontSize": { "value": 3, "unit": "rem" }
      }
    }
  }
}

Summary

  • Run npx @google/design.md export --format dtcg DESIGN.md for a one-line CLI conversion to W3C DTCG format.
  • The DtcgEmitterHandler class in packages/cli/src/linter/dtcg/handler.ts powers the conversion programmatically.
  • Internal helpers such as colorToValue, dimToValue, and typographyToValue map raw values to the 2025.10 DTCG schema.
  • Outputs include typed groups for color, spacing, rounded, and typography with full $schema compliance.

Frequently Asked Questions

What DTCG schema version does design.md support?

The emitter targets the 2025.10 DTCG schema. It injects https://www.designtokens.org/schemas/2025.10/format.json into the $schema field of the generated tokens.json file.

Can I export DESIGN.md tokens to formats other than DTCG?

Yes. The CLI entry point in packages/cli/src/commands/export.ts selects an emitter based on the --format argument, so additional handlers can be registered alongside DtcgEmitterHandler.

How are color values represented in the DTCG output?

The colorToValue helper converts each color into an sRGB array under components and a hexadecimal string under hex, wrapped in a $value object with colorSpace: "srgb".

Is the DTCG export available through both the CLI and the API?

Both paths are supported. You can run export --format dtcg from the terminal for immediate file generation, or instantiate DtcgEmitterHandler directly in TypeScript for custom build pipelines.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →