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
| Type | Format | Example |
|---|---|---|
| Color | # + hex (sRGB) | "#1A1C1E" |
| Dimension | number + px, em, rem | 48px, -0.02em |
| Token reference | {path.to.token} | {colors.primary} |
| Typography | object: 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:
- Overview (alias: Brand & Style)
- Colors
- Typography
- Layout (alias: Layout & Spacing)
- Elevation & Depth (alias: Elevation)
- Shapes
- Components
- 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:
| Rule | Severity | What it catches |
|---|---|---|
broken-ref | error | {colors.missing} points at a non-existent token |
duplicate-section | error | Same ## Heading appears twice |
invalid-color | error | Hex value doesn't parse |
invalid-dimension | error | Value doesn't match dimension format |
invalid-typography | error | Typography object has wrong field types |
wcag-contrast | warning/info | Component textColor vs backgroundColor ratio below WCAG AA (4.5:1) or AAA (7:1) |
unknown-component-property | warning | Property outside the whitelist |
Export Formats
| Format | Flag | Output |
|---|---|---|
| Tailwind v3 theme | --format tailwind or --format json-tailwind | theme: { colors: {...}, fontFamily: {...}, ... } |
| Tailwind v4 CSS | --format css-tailwind | @theme { --color-primary: #...; } |
| W3C DTCG | --format dtcg | JSON 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
| Property | Purpose |
|---|---|
$type | Token type identifier (required) |
$value | Token value (required) |
$description | Optional human-readable note |
$extensions | Tool-specific metadata |
$deprecated | Deprecation 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
insetboolean 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— hasflutter/class.dartbut produces flat const classes - The missing piece is a DESIGN.md → Flutter exporter that generates idiomatic
ThemeExtensionsubclasses,TextStyleobjects,EdgeInsets,BorderRadius, and a Material 3ColorSchememapping
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
| Approach | Quality | Effort |
|---|---|---|
Style Dictionary flutter/class.dart | Flat const class, no ThemeData integration | Low (one config entry) |
| Manual ThemeExtension subclassing | Idiomatic, type-safe, full lerp/merge | Medium (hand-coded) |
| Custom DTCG → Flutter generator | Best of both worlds | One-time script (80-100 lines) |
| DESIGN.md → Flutter exporter | Direct pipeline from agent spec | Not 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:
- Parse the YAML frontmatter (or the DTCG export)
- Map
colors.*→Colorconstants - Map
typography.*→TextStyleobjects (combining fontFamily, fontSize, fontWeight, lineHeight, letterSpacing) - Map
spacing.*→EdgeInsets.all(n)orEdgeInsets.symmetric() - Map
rounded.*→BorderRadius.circular(n) - Map
components.*→ThemeExtensionsubclasses - Template all of this into a valid
.dartfile 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
- google-labs-code/design.md — the spec repo, Apache-2.0
- @google/design.md on npm — the CLI tool
- W3C DTCG Format 2025.10 — the standard
- Amazon Style Dictionary — build-time token transformer
- Tokens Studio — Figma design token plugin
- Specify — design token management platform
- Spec — design token development platform
- Flutter ThemeExtension — Flutter's native theme extension mechanism