Google DESIGN.md & The Design Token Ecosystem

Created: 2026-05-15 | Tags: design-tokens, design-systems, dtcg, style-dictionary, google, figma, flutter

A thorough exploration of Google's DESIGN.md spec — a YAML+markdown file format for describing a visual identity to coding agents — and how it fits into the broader design token ecosystem: W3C DTCG, Style Dictionary, Figma Tokens/Tokens Studio, and the pipeline to platform-specific formats including Flutter.


1. The Problem: Design Handoff to AI

AI coding agents are good at implementing from a spec, but they have no way to know what color #1A1C1E means in your design system. Is it a heading color? A border? The brand primary? An agent seeing #B8422E in a component has no idea it's the single interaction color — Boston Clay — reserved for primary buttons and links.

Traditional design handoff relies on Figma inspect mode, design docs, or oral tradition ("just use the same red as the homepage"). None of these are machine-readable. An agent would need to read every component, infer the pattern, and hope it's right.

DESIGN.md solves this by putting the entire visual identity into a single file that is both:

  • Machine-readable — YAML frontmatter with exact token values, component definitions, and token references ({colors.primary})
  • Human-readable — Markdown prose explaining why those values exist, how to apply them, and what's the brand philosophy

It was created by google-labs-code, Apache-2.0 licensed, currently in alpha (v0.1.1 on npm, 13.9k+ stars on GitHub). The spec is maintained as a single canonical TYPE_CHECK.md that both documents the format and validates itself.


2. The DESIGN.md File Format

Anatomy

A DESIGN.md file has two parts:

YAML frontmatter (between the first two --- delimiters) — machine tokens:

---
version: alpha
name: Heritage
description: Architectural minimalism meets journalistic gravitas.
colors:
  primary: "#1A1C1E"
  secondary: "#6C7278"
  tertiary: "#B8422E"
  neutral: "#F7F5F2"
typography:
  h1:
    fontFamily: Public Sans
    fontSize: 48px
    fontWeight: 600
    lineHeight: 1.1
    letterSpacing: "-0.02em"
  body-md:
    fontFamily: Public Sans
    fontSize: 16px
    fontWeight: 400
    lineHeight: 1.5
rounded:
  sm: 4px
  md: 8px
  lg: 16px
spacing:
  sm: 8px
  md: 16px
  lg: 24px
components:
  button-primary:
    backgroundColor: "{colors.tertiary}"
    textColor: "#FFFFFF"
    rounded: "{rounded.sm}"
  button-primary-hover:
    backgroundColor: "{colors.primary}"
---

Markdown body — human rationale in canonical sections:

## Overview

Architectural Minimalism meets Journalistic Gravitas...

## Colors

- **Primary (#1A1C1E):** Deep ink for headlines and core text.
- **Tertiary (#B8422E):** "Boston Clay" — the sole driver for interaction.

## Typography

Public Sans for everything except small all-caps labels...

## Components

`button-primary` is the only high-emphasis action on a page...

Token Types

TypeFormatExample
Color# + hex (sRGB)"#1A1C1E"
Dimensionnumber + px, em, rem48px, -0.02em
Token reference{path.to.token}{colors.primary}
Typographyobject: fontFamily, fontSize, fontWeight, lineHeight, letterSpacing, fontFeature, fontVariation{ fontFamily: Inter, fontSize: 16px }

Component Model

Components are defined with a whitelisted set of properties: backgroundColor, textColor, typography, rounded, padding, size, height, width.

Variants (hover, active, pressed) are sibling entries, not nested. This is a deliberate design choice — it keeps the YAML flat and unambiguous:

components:
  button-primary:
    backgroundColor: "{colors.tertiary}"
  button-primary-hover:
    backgroundColor: "{colors.primary}"
  button-primary-pressed:
    backgroundColor: "{colors.secondary}"

Not:

# WRONG — no nested variants
components:
  button-primary:
    hover:
      backgroundColor: ...

Token References

The {path.to.token} syntax resolves to other token values. References can chain: {colors.primary}, {rounded.md}, {typography.h1.fontSize}. This is the key mechanism for keeping the palette single-source — component colors reference the palette rather than duplicating hex values.

Canonical Section Order

Sections are optional, but present ones MUST appear in this order:

  1. Overview (alias: Brand & Style)
  2. Colors
  3. Typography
  4. Layout (alias: Layout & Spacing)
  5. Elevation & Depth (alias: Elevation)
  6. Shapes
  7. Components
  8. Do's and Don'ts

Duplicate headings reject the file. Unknown sections and token names are preserved (not errored), but unknown component properties produce a warning.


3. The CLI: @google/design.md

Published on npm at @google/design.md@0.1.1. No global install required — use via npx.

# Validate structure, token references, and WCAG contrast
npx @google/design.md lint DESIGN.md

# Token-level diff between versions
npx @google/design.md diff DESIGN.md DESIGN-v2.md

# Export to Tailwind v3 theme JSON
npx @google/design.md export --format tailwind DESIGN.md

# Export to Tailwind v4 CSS @theme format
npx @google/design.md export --format css-tailwind DESIGN.md

# Export to W3C DTCG (Design Tokens Format Module) JSON
npx @google/design.md export --format dtcg DESIGN.md > tokens.json

# Print the spec schema itself (for injecting into agent prompts)
npx @google/design.md spec

Lint Rules

The linter checks 7 rule categories:

RuleSeverityWhat it catches
broken-referror{colors.missing} points at a non-existent token
duplicate-sectionerrorSame ## Heading appears twice
invalid-colorerrorHex value doesn't parse
invalid-dimensionerrorValue doesn't match dimension format
invalid-typographyerrorTypography object has wrong field types
wcag-contrastwarning/infoComponent textColor vs backgroundColor ratio below WCAG AA (4.5:1) or AAA (7:1)
unknown-component-propertywarningProperty outside the whitelist

Export Formats

FormatFlagOutput
Tailwind v3 theme--format tailwind or --format json-tailwindtheme: { colors: {...}, fontFamily: {...}, ... }
Tailwind v4 CSS--format css-tailwind@theme { --color-primary: #...; }
W3C DTCG--format dtcgJSON conforming to the DTCG spec

Currently only Tailwind and DTCG. No Flutter, no CSS custom properties, no Android. These are community-contribution opportunities.

Windows Note

On Windows, the tool is aliased as designmd because the .md extension confuses Windows's file-type association system with Markdown files. Use npx @google/design.md ... (works everywhere) or designmd ... on Windows.


4. The W3C DTCG Standard

The Design Tokens Community Group format is the industry interchange standard for design tokens. Version 2025.10 (Final Community Group Report, October 28, 2025) is the current release. Editors: Louis Chenais, Kathleen McMahon, Drew Powers, Matthew Ström-Awn, Donna Vitan.

Format

DTCG defines tokens as JSON objects with $-prefixed properties:

{
  "color/primary": {
    "$type": "color",
    "$value": { "colorSpace": "srgb", "components": [0.102, 0.110, 0.118], "hex": "#1A1C1E" }
  },
  "typography/h1": {
    "$type": "typography",
    "$value": {
      "fontFamily": "Public Sans",
      "fontSize": { "value": 48, "unit": "px" },
      "fontWeight": 600,
      "lineHeight": { "value": 52.8, "unit": "px" },
      "letterSpacing": { "value": -0.02, "unit": "em" }
    }
  }
}

Token Types (Section 8 of the spec)

Simple types: color, dimension, fontFamily, fontWeight, duration, cubicBezier, number

Composite types (Section 9): strokeStyle, border, transition, shadow, gradient, typography

Key Properties

PropertyPurpose
$typeToken type identifier (required)
$valueToken value (required)
$descriptionOptional human-readable note
$extensionsTool-specific metadata
$deprecatedDeprecation message — consumers should warn

Reference Syntax

Two supported syntaxes:

  • Curly brace (recommended): {color/primary} — the same syntax used by DESIGN.md
  • JSON Pointer: #/color/primary

Color Spaces

DTCG supports 14 color spaces: srgb, srgb-linear, display-p3, a98-rgb, prophoto-rgb, rec2020, xyz-d50, xyz-d65, lab, lch, oklab, oklch, hsl, hwb. This is a superset of the web's srgb — crucial for professional design tools that work in Display P3 (Apple ecosystem), Oklch (perceptually uniform), or Lab (color science).

Role in the Ecosystem

DTCG is the interchange format — the JSON that all tools can read and write:

Figma (via Tokens Studio) → DTCG JSON → GitHub repo
                                              ↓
                              Style Dictionary (reads DTCG) → platform outputs
                                              ↓
                              @google/design.md export --format dtcg

DESIGN.md's export --format dtcg produces valid DTCG JSON, bridging the agent-facing spec with the tool ecosystem.


5. Style Dictionary

Amazon's Style Dictionary (style-dictionary@5.4.0) is a build-time transformer that reads design tokens and generates platform-specific code. "Style once, use everywhere."

Configuration

{
  "source": ["tokens/**/*.json"],
  "platforms": {
    "scss": {
      "transformGroup": "scss",
      "buildPath": "build/",
      "files": [{ "destination": "_variables.scss", "format": "scss/variables" }]
    },
    "flutter": {
      "transformGroup": "flutter",
      "buildPath": "build/flutter/",
      "files": [{ "destination": "tokens.dart", "format": "flutter/class.dart" }]
    }
  }
}

DTCG Support (v5)

Style Dictionary v5 has full DTCG input support, added incrementally:

  • v5.3.0: Full DTCG structured color format (14 color spaces)
  • v5.3.1: Shadow/border CSS shorthand DTCG
  • v5.3.3: DTCG inset boolean for shadow
  • v5.4.0: DTCG dimension token type object value support

Flutter Output

Style Dictionary ships with a flutter/class.dart format:

import 'package:flutter/material.dart';

class StyleDictionary {
  StyleDictionary._();

  static const colorBrandPrimary = Color(0xFFFF5FFF);
  static const sizeFontSizeMedium = 16.00;
  static const contentFontFamily1 = "NewJune";
}

Options: className, outputReferences, showFileHeader. The output is a flat static const class — basic but functional. Styles Dict constructs Color from hex, leaves num for dimensions, and passes strings through.

Other Output Formats

Built-in formats cover all major platforms: css/variables, scss/variables, less/variables, javascript/module, typescript/es6-declarations, android/resources, ios-swift/class.swift, compose/object, json, json/nested. Custom formats are plain JavaScript functions — you write a transformer that takes token data and returns a string.

Custom Transforms

Style Dictionary's power is the transform system. A transform is a JavaScript function:

// Register a custom Flutter transform
StyleDictionary.registerTransform({
  name: 'flutter/spacing',
  type: 'value',
  matcher: (token) => token.attributes.category === 'spacing',
  transformer: (token) => {
    const value = parseFloat(token.original.value);
    return `EdgeInsets.all(${value})`;
  },
});

You can compose transforms into transformGroup — a named pipeline applied per platform. The built-in flutter/class.dart format combined with custom transforms can produce rich Flutter output: EdgeInsets from spacing, BorderRadius from rounded, TextStyle from typography composites.


6. Figma Tokens & Tokens Studio

Figma Tokens (Original)

The original Figma Tokens plugin (figma-tokens@0.0.8, abandoned since 2022) was a CLI to extract Figma variables as design tokens. It fed into Style Dictionary.

Tokens Studio (Active)

Tokens Studio (formerly Figma Tokens) is the current active plugin for visual design token management inside Figma. Key capabilities:

  • Visual editor — create and edit tokens through a UI, organized in groups
  • GitHub sync — push/pull DTCG JSON directly to a repository
  • Multi-file — tokens can span multiple files (colors.json, typography.json)
  • Theming — token sets for light, dark, high-contrast, brand variants
  • Expressions — math operations on token values (spacing.lg * 2)
  • Figma variables — bi-directional sync with Figma's native variables

Pipeline: Figma (design) → Tokens Studio plugin → GitHub (DTCG JSON) → Style Dictionary → platform outputs. The DTCG JSON in the repo is the same format that DESIGN.md exports and Style Dictionary ingests.


7. Specify & Spec

Specify (specifyapp.com) and Spec (spec.dev) are commercial design token management platforms that provide visual editing, versioning, and multi-format export. They sit between the design tool and the codebase, acting as a managed token repository with webhook-triggered exports. They compete with the open-source Style Dictionary + GitHub approach, but don't add fundamentally new capabilities — they manage the same DTCG tokens through a UI and handle the CI/CD pipeline.


8. Getting Started: From DESIGN.md to Running Code

End-to-End: DESIGN.md → Flutter

There is no direct Flutter exporter for DESIGN.md yet. The pipeline requires an intermediate step:

DESIGN.md
    │
    ├─ npx @google/design.md export --format dtcg → tokens.json
    │     │
    │     └─ Style Dictionary (flutter/class.dart) → flat Dart class
    │
    └─ (missing) Custom script → ThemeExtension + ThemeData → idiomatic Flutter

Current state:

  • @google/design.md@0.1.1 — no Flutter export format. Only Tailwind and DTCG.
  • Style Dictionary @5.4.0 — has flutter/class.dart but produces flat const classes
  • The missing piece is a DESIGN.md → Flutter exporter that generates idiomatic ThemeExtension subclasses, TextStyle objects, EdgeInsets, BorderRadius, and a Material 3 ColorScheme mapping

A custom Flutter exporter would be approximately 80-100 lines of Python: parse the DTCG JSON, map each token type to its Flutter counterpart, template the Dart code. This is the same pattern Style Dictionary's flutter/class.dart format uses internally.

End-to-End: DESIGN.md → Tailwind CSS

DESIGN.md
    │
    npx @google/design.md export --format json-tailwind DESIGN.md > tailwind.config.theme.json
    │
    import in tailwind.config.js: theme: require('./tailwind.config.theme.json')

This is the most mature pipeline — directly supported by the CLI, no intermediate steps.

End-to-End: DESIGN.md → CSS Custom Properties

No direct export. The workaround is via DTCG:

DESIGN.md → export dtcg → tokens.json → Style Dictionary (css/variables) → variables.css

Or wait for a community --format css exporter for @google/design.md.


9. Relevance to Flutter

The Gap

Flutter has no official design token pipeline. The framework has ThemeData, ThemeExtension<MyTheme>, and ColorScheme — a complete theming system — but no standardized way to get tokens FROM a design spec INTO that system.

Current Approaches

ApproachQualityEffort
Style Dictionary flutter/class.dartFlat const class, no ThemeData integrationLow (one config entry)
Manual ThemeExtension subclassingIdiomatic, type-safe, full lerp/mergeMedium (hand-coded)
Custom DTCG → Flutter generatorBest of both worldsOne-time script (80-100 lines)
DESIGN.md → Flutter exporterDirect pipeline from agent specNot yet built — needs community contribution

What an Idiomatic Flutter Exporter Would Produce

From a DESIGN.md → DTCG pipeline, the ideal Flutter output:

// Auto-generated from design token spec
class WikiTokens extends ThemeExtension<WikiTokens> {
  const WikiTokens({
    required this.primaryColor,
    required this.secondaryColor,
    required this.headlineTextStyle,
    required this.bodyTextStyle,
    required this.smallSpacing,
    required this.mediumSpacing,
    required this.smallRadius,
    required this.mediumRadius,
  });

  final Color primaryColor;
  final Color secondaryColor;
  final TextStyle headlineTextStyle;
  final TextStyle bodyTextStyle;
  final EdgeInsets smallSpacing;
  final EdgeInsets mediumSpacing;
  final BorderRadius smallRadius;
  final BorderRadius mediumRadius;

  @override
  WikiTokens copyWith({...}) => WikiTokens(...);

  @override
  WikiTokens lerp(WikiTokens? other, double t) => WikiTokens(
    primaryColor: Color.lerp(primaryColor, other?.primaryColor, t)!,
    // ... lerp for each field
  );

  static ThemeData get light => ThemeData(
    colorScheme: ColorScheme.fromSeed(seedColor: primaryColor),
    textTheme: TextTheme(
      headlineLarge: headlineTextStyle,
      bodyLarge: bodyTextStyle,
    ),
    extensions: [const WikiTokens(...)],
  );
}

And access in widgets:

final tokens = Theme.of(context).extension<WikiTokens>()!;
Container(
  color: tokens.primaryColor,
  padding: tokens.smallSpacing,
  child: Text('Hello', style: tokens.bodyTextStyle),
)

The Missing Piece

A Flutter exporter for DESIGN.md needs to:

  1. Parse the YAML frontmatter (or the DTCG export)
  2. Map colors.*Color constants
  3. Map typography.*TextStyle objects (combining fontFamily, fontSize, fontWeight, lineHeight, letterSpacing)
  4. Map spacing.*EdgeInsets.all(n) or EdgeInsets.symmetric()
  5. Map rounded.*BorderRadius.circular(n)
  6. Map components.*ThemeExtension subclasses
  7. Template all of this into a valid .dart file with proper imports

This is exactly the kind of transformation that Style Dictionary's custom format system supports natively — you write a JavaScript function that takes the parsed token tree and returns a string. The missing format is just waiting for someone to write it.


10. The Ecosystem Map

                         ┌─────────────────┐
                         │  DESIGN.md      │  ← Agent-authorable, single file
                         │  (google-labs)  │
                         └────────┬────────┘
                                  │ export --format dtcg
                                  ▼
┌──────────────┐        ┌─────────────────┐        ┌──────────────────┐
│  Figma       │ ──────▶│  DTCG JSON      │◀───────│  DESIGN.md CLI   │
│  Tokens      │  sync  │  (W3C standard) │  export │  (agent-facing)  │
│  Studio      │        └────────┬────────┘        └──────────────────┘
└──────────────┘                 │
                                │ read
                                ▼
                       ┌──────────────────┐
                       │  Style Dict      │───▶ scss/variables
                       │  (Amazon)        │───▶ flutter/class.dart
                       │  v5.4.0          │───▶ ios-swift/class.swift
                       └──────────────────┘───▶ android/resources
                                                ─── custom formats

Missing: DESIGN.md ──▶ Flutter ThemeData + ThemeExtension exporter

The key insight is that DESIGN.md is agent-facing (for AI coding agents to consume design intent) while DTCG is tool-facing (for interchange between Figma, Style Dictionary, and code generation). They converge at DTCG JSON — DESIGN.md can export it, Tokens Studio can produce it, and Style Dictionary can consume it. The remaining gap is a Flutter format generator that produces idiomatic theme code rather than flat const classes.


References