DESIGN.md
A format specification for describing a visual identity to coding agents. It gives AI agents a persistent, structured understanding of a design system so stylistic choices stay consistent across design sessions and between different agents/tools. It’s a human-readable, open-format living source of truth that both humans and AI can refine.
Made by Google Labs (used in Stitch). Currently at version alpha — expect the format to change.
The Core Idea
A DESIGN.md file combines two layers:
- YAML front matter — machine-readable design tokens (colors, typography, spacing…). These are the normative values.
- Markdown body — human-readable design rationale/prose organized into
##sections. This tells the agent why the values exist and how to apply them.
Tokens give agents exact values. Prose tells them why those values exist and how to apply them. The tokens are context/reference — not rendering instructions.
An agent reading the file will produce a UI matching both the exact token values and the described intent.
Minimal example
---
name: Heritage
colors:
primary: "#1A1C1E"
secondary: "#6C7278"
tertiary: "#B8422E"
neutral: "#F7F5F2"
typography:
h1: { fontFamily: Public Sans, fontSize: 3rem }
body-md: { fontFamily: Public Sans, fontSize: 1rem }
rounded: { sm: 4px, md: 8px }
spacing: { sm: 8px, md: 16px }
---
## Overview
Architectural Minimalism meets Journalistic Gravitas. The UI evokes a
premium matte finish — a high-end broadsheet or contemporary gallery.
## Colors
The palette is rooted in high-contrast neutrals and a single accent color.
- **Primary (#1A1C1E):** Deep ink for headlines and core text.
- **Tertiary (#B8422E):** "Boston Clay" — the sole driver for interaction.Philosophy — Prose is the Point
The most important idea in DESIGN.md: the quality of a generated design is determined less by the precision of its values than by how clearly the intent is described. The prose is where the design actually lives; everything else supports it.
Key principles:
-
A specific reference beats a list of adjectives. “A 1970s graduate lecture handout in the tradition of an old, established university” evokes a complete world (one ink color, generous margins, serif at reading size, no decoration). “Modern, clean, trustworthy, premium” evokes nothing specific — the model lands in generic center-mass. Adjectives describe a region; a specific reference describes a point.
-
Negative constraints arrive for free. Naming a concrete reference automatically carries its restrictions — a model knows a lecture handout doesn’t glow or use gradients, the same way “dog” tells it dogs don’t meow. A short intentional Do’s/Don’ts list is the sweet spot; a long rambling one is usually a sign the reference was too vague.
-
Tokens are context, not requirements. DESIGN.md generally does not recommend token requirements in the spec. Tokens serve as reference points named in the prose — this avoids reinventing decades of work by existing design languages and tools.
-
The format grows through its users, not its spec. The spec standardizes only the universal minimum (name + colors, typography, spacing, rounded, components). Everything else — motion, iconography, elevation, text casing, paragraph measure — is yours to define. It accepts any key, any section, any structure. The linter accepts custom values and agents just read the prose; no spec change needed because tokens are context, not instruction.
Specification
File structure
- Front matter block must start and end with a line containing exactly
---. - Body uses
##(<h2>) headings for sections. An optional#(<h1>) title is allowed but not parsed as a section. - Tokens are inspired by the W3C Design Token Format — convertible to/from
tokens.json, Figma variables, Tailwind theme configs.
Token schema
version: <string> # optional, current: "alpha"
name: <string>
description: <string> # optional
colors:
<token-name>: <Color>
typography:
<token-name>: <Typography>
rounded:
<scale-level>: <Dimension>
spacing:
<scale-level>: <Dimension | number>
components:
<component-name>:
<token-name>: <string | token reference><scale-level> = a named level like xs, sm, md, lg, xl, full (any descriptive string is valid).
Token types
| Type | Format | Example |
|---|---|---|
| Color | Any valid CSS color: hex (#RGB/#RGBA/#RRGGBB/#RRGGBBAA), named, rgb()/rgba()/hsl()/hwb(), wide-gamut oklch()/oklab()/lch()/lab(), color-mix() | "#1A1C1E", "oklch(62% 0.18 250)" |
| Dimension | number + unit (px, em, rem) | 48px, -0.02em |
| Token Reference | {path.to.token} — must point to a primitive (except in components, where composite refs like {typography.label-md} are allowed) | {colors.primary} |
| Typography | object: fontFamily, fontSize, fontWeight, lineHeight, letterSpacing, fontFeature, fontVariation | see below |
- Colors are internally converted to sRGB for WCAG contrast checks; original format preserved for display/export. Hex is the recommended default.
lineHeightaccepts a Dimension or a unitless multiplier number (e.g.1.6) — unitless is recommended CSS practice.fontWeightmay be a bare number or quoted string (equivalent).
Section order
Sections can be omitted, but those present must appear in this order:
| # | Section | Aliases |
|---|---|---|
| 1 | Overview | Brand & Style |
| 2 | Colors | |
| 3 | Typography | |
| 4 | Layout | Layout & Spacing |
| 5 | Elevation & Depth | Elevation |
| 6 | Shapes | |
| 7 | Components | |
| 8 | Do’s and Don’ts |
What each section is for:
- Overview — holistic look & feel: brand personality, target audience, emotional response (playful/professional, dense/spacious). High-level fallback context.
- Colors — at least
primarymust be defined. Common role order:primary,secondary,tertiary,neutral. - Typography — usually 9–15 levels; semantic categories (
headline,display,body,label,caption) × sizes (sm/md/lg). - Layout — grid/spacing strategy (fluid grid, fixed-max-width, margins/safe areas).
- Elevation & Depth — how hierarchy is conveyed (shadows vs. tonal layers vs. borders for flat designs).
- Shapes — corner radius language via
roundedtokens. - Components — style guidance for atoms (buttons, chips, inputs, tooltips, etc.).
- Do’s and Don’ts — guardrails and common pitfalls.
Components
Map a component name to sub-token properties. Values may be literals or references.
components:
button-primary:
backgroundColor: "{colors.tertiary}"
textColor: "{colors.on-tertiary}"
rounded: "{rounded.sm}"
padding: 12px
button-primary-hover:
backgroundColor: "{colors.tertiary-container}"- Valid properties:
backgroundColor,textColor,typography,rounded,padding,size,height,width. - Variants (hover, active, pressed) = separate entries with related key names (
button-primary,button-primary-hover,button-primary-active). The agent considers all variants together. - The components spec is intentionally flexible and actively evolving.
Recommended token names (non-normative)
- Colors:
primary,secondary,tertiary,neutral,surface,on-surface,error - Typography:
headline-display,headline-lg/md,body-lg/md/sm,label-lg/md/sm - Rounded:
none,sm,md,lg,xl,full
Consumer behavior for unknown content
| Scenario | Behavior |
|---|---|
Unknown section heading (## Iconography) | Preserve; don’t error |
| Unknown color token name | Accept if value valid |
| Unknown typography token name | Accept as valid typography |
| Unknown spacing value | Accept; store as string if not a valid dimension |
Unknown component property (borderColor) | Accept with warning |
Duplicate section heading (two ## Colors) | Error; reject the file |
Extending the format (custom sections)
Because tokens are context (not instruction), you can add whole domains the spec doesn’t standardize — the linter accepts them and agents read the prose. E.g. Motion:
## Motion
```yaml
motion:
feedback: 120ms
content: 250ms
easing: 'cubic-bezier(0.2, 0, 0, 1)'
```
Transitions are quick and mechanical. Nothing bounces or lingers.
- Interactive feedback (hover, press): {motion.feedback}, always {motion.easing}.
- Nothing animates longer than 300ms. Respect `prefers-reduced-motion`.CLI — @google/design.md
npm install @google/design.md
# or run directly:
npx @google/design.md lint DESIGN.mdAll commands accept a file path or - for stdin. Output defaults to JSON.
Windows/PowerShell gotcha: the
.mdin the bin name collides with the Markdown file association. Use the dot-free alias:npx -p @google/design.md designmd lint DESIGN.md. Inpackage.jsonscripts also use thedesignmdalias.ENOVERSIONSusually means npm isn’t hitting the public registry (npm config get registryshould behttps://registry.npmjs.org/).
lint — validate structure
npx @google/design.md lint DESIGN.md
cat DESIGN.md | npx @google/design.md lint -Exit code 1 if errors found, else 0. Returns findings + summary as JSON:
{ "findings": [ { "severity": "warning", "path": "components.button-primary",
"message": "textColor (#ffffff) on backgroundColor (#1A1C1E) has contrast ratio 15.42:1 — passes WCAG AA." } ],
"summary": { "errors": 0, "warnings": 1, "info": 1 } }diff — compare two versions
npx @google/design.md diff DESIGN.md DESIGN-v2.mdReports token-level added/removed/modified + a regression boolean. Exit 1 if regressions detected (more errors/warnings in the “after” file).
export — convert tokens to other formats
npx @google/design.md export --format json-tailwind DESIGN.md > tailwind.theme.json
npx @google/design.md export --format css-tailwind DESIGN.md > theme.css
npx @google/design.md export --format dtcg DESIGN.md > tokens.json| Format | Output | Description |
|---|---|---|
json-tailwind (alias tailwind) | JSON | Tailwind v3 theme.extend config |
css-tailwind | CSS | Tailwind v4 @theme { … } block with CSS custom props (--color-*, --font-*, --radius-*, --spacing-*…) |
dtcg | JSON | W3C Design Tokens Format Module |
Exit 0 on successful export (regardless of lint findings — run lint to gate), 1 on invalid format/emitter error, 2 if input unreadable.
spec — output the spec (for injecting into agent prompts)
npx @google/design.md spec # full spec markdown
npx @google/design.md spec --rules # + linting rules table
npx @google/design.md spec --rules-only --format jsonThis is the “get instructions” use case: pipe the spec into an agent’s context so it knows the format before generating/editing a DESIGN.md.
Programmatic API
import { lint } from '@google/design.md/linter';
const report = lint(markdownString);
report.findings; // Finding[]
report.summary; // { errors, warnings, info }
report.designSystem; // parsed DesignSystemStateLinting Rules
The linter runs nine rules against a parsed DESIGN.md, each at a fixed severity:
| Rule | Severity | Checks |
|---|---|---|
broken-ref | error | Token refs ({colors.primary}) that don’t resolve to a defined token |
missing-primary | warning | Colors defined but no primary — agents will auto-generate one |
contrast-ratio | warning | Component backgroundColor/textColor pairs below WCAG AA (4.5:1) |
orphaned-tokens | warning | Color tokens defined but never referenced by any component |
missing-typography | warning | Colors defined but no typography — agents fall back to default fonts |
section-order | warning | Sections out of canonical order |
unknown-key | warning | Top-level YAML key that looks like a typo of a schema key (colours: → colors:); genuine custom extension keys stay silent |
token-summary | info | Count of tokens defined per section |
missing-sections | info | Optional sections (spacing, rounded) absent when other tokens exist |
Interoperability
Tokens are inspired by the W3C Design Token Format and export to:
- Tailwind v3 JSON config (
json-tailwind) - Tailwind v4 CSS
@themeblock (css-tailwind) - DTCG
tokens.json(W3C Design Tokens Format Module)
Related
- Repo: https://github.com/google-labs-code/design.md
- Collection/directory: https://getdesign.md
- Used by: Stitch — Design with AI
- Concepts: Building effective agents, design tokens, prompt context engineering