learn.aathan.in

How to Write a design.md File

A detailed guide to authoring a design.md — the single source of truth for a product's visual and interaction system.

What a design.md is

A design.md (often committed as DESIGN.md) is a single, plain-text file that describes a product’s design system — its colors, typography, spacing, components, and the rules for using them — in a format that is readable by both humans and AI coding agents. It sits in your repository, changes through pull requests, and acts as the single source of truth for how your UI should look and feel.

The mental model that lands best with developers: it’s a tsconfig.json for your design system. One canonical file, in version control, that every tool and teammate defers to instead of re-inventing the look each time.

The format grew out of Google Stitch (the AI design tool formerly known as Galileo AI), where it was the artifact Stitch used to describe a design system to itself. Google open-sourced the DESIGN.md format in 2026 so other tools could read and write it, and the reference spec and CLI now live at google-labs-code/design.md.

Why it exists

Before design.md, keeping generated or hand-written UI on-brand meant re-describing your palette and type scale in every prompt, every Figma file, and every onboarding doc — and hoping they stayed in sync. A design.md collapses that into one file with two jobs:

  • For humans — a concise, skimmable reference for the visual language: what “primary” means, when to use the serif, how much a card should round.
  • For AI coding assistants — a structured spec that tools like Claude Code, Cursor, v0, Lovable, and Google Stitch can read directly so the UI they generate matches your brand without you re-describing it every prompt. Any tool that can read the file is meant to honor the same rules — write it once, reuse it everywhere.

That dual audience is the whole design of the format: machine-readable tokens carry the exact values, and human-readable prose carries the why — and, crucially, the when-not-to.

The two-part anatomy

A design.md file has two layers stacked in one file:

  1. YAML front matter — the design tokens: exact color values, the type scale, spacing steps, corner radii, and component definitions. This is the source of truth for values.
  2. Markdown body — prose organized into ordered ## sections that explains the reasoning behind those tokens and tells the agent how to apply them.
---
version: 1.0.0
name: Aathan Games Hub
description: Dark-first arcade hub — serif display, mono tags, warm accent.
colors:
  primary: "#E8B84B"
  surface: "#0E0E10"
  on-surface: "#F5F3EE"
typography:
  headline-display:
    fontFamily: '"Fraunces", Georgia, serif'
    fontSize: 3.5rem
    fontWeight: 600
    lineHeight: 1.05
spacing:
  sm: 8px
  md: 16px
  lg: 24px
rounded:
  md: 12px
---

## Overview
Dark-first, editorial-arcade. A warm amber accent on near-black...

## Colors
...

Everything above the second --- is tokens a machine can parse; everything below is guidance a human (or an agent) reads. Keep both in the same file so they can never drift apart.

The reference spec mandates a fixed order of ## sections so that any tool knows where to look. Follow it:

#SectionWhat it covers
1Overview (Brand & Style)Brand voice, mood, the one-paragraph “feel”
2ColorsSemantic palette, light/dark, usage rules
3TypographyFont families and the type scale
4Layout (Layout & Spacing)Grid, spacing scale, breakpoints
5Elevation & DepthShadows / layering strategy
6ShapesCorner-radius language
7ComponentsPer-component recipes built from tokens
8Do’s and Don’tsPractical guardrails

You can add Motion & Easing and Accessibility as their own sections — they matter enough to be explicit, and good design.md files call them out rather than burying them. The sections below show what strong content looks like for each, using one worked example throughout: a dark-first hub with a serif display face and monospace tags (the shape of a small arcade/games landing site).

1. Overview — brand voice and mood

Open with a short paragraph a newcomer could read in fifteen seconds. State the mood, the one or two defining moves, and what to avoid. This is the prose that stops an AI agent from generating a generic Bootstrap-looking page.

## Overview
Dark-first and editorial-arcade. Near-black surfaces, one warm amber accent,
and a high-contrast serif display face paired with a monospace for tags and
metadata. The feel is "a well-set magazine that happens to be an arcade" —
confident typography, generous negative space, restrained color. Avoid
gradients, drop shadows, and more than one accent hue.

2. Colors — semantic tokens, light and dark

Name tokens by role, not by value. primary and surface survive a rebrand; amber-500 and near-black do not. Provide light and dark values where relevant, and pair the token table with rules for when each is used.

colors:
  primary:      "#E8B84B"   # warm amber — actions, focus, highlights
  on-primary:   "#1A1400"   # text/icons on primary
  surface:      "#0E0E10"   # page background (dark)
  surface-alt:  "#17171B"   # cards, raised panels
  on-surface:   "#F5F3EE"   # body text
  muted:        "#9B9AA0"   # secondary text, metadata
  border:       "#2A2A30"   # hairlines, dividers
  error:        "#E5484D"
TokenDarkLightUse for
surface#0E0E10#FBFAF7Page background
surface-alt#17171B#FFFFFFCards, panels
on-surface#F5F3EE#1A1A1EPrimary text
primary#E8B84B#B57E12Accent, actions, focus rings
muted#9B9AA0#6B6A70Metadata, captions

Semantic naming rule: components reference {colors.primary}, never a raw hex. Change the brand by editing one token; every consumer follows.

3. Typography — families and a modular scale

Declare the families and a type scale with named levels. A modular scale (each step a fixed ratio above the last) keeps sizes harmonious. The example uses a ~1.25 (major third) ratio from a 1rem base.

typography:
  headline-display:
    fontFamily: '"Fraunces", Georgia, serif'
    fontSize: 3.5rem
    fontWeight: 600
    lineHeight: 1.05
    letterSpacing: "-0.02em"
  headline-lg:
    fontFamily: '"Fraunces", Georgia, serif'
    fontSize: 2rem
    fontWeight: 600
    lineHeight: 1.15
  body-md:
    fontFamily: 'Inter, system-ui, sans-serif'
    fontSize: 1rem
    fontWeight: 400
    lineHeight: 1.6
  label-mono:
    fontFamily: '"JetBrains Mono", ui-monospace, monospace'
    fontSize: 0.8125rem
    fontWeight: 500
    letterSpacing: "0.02em"
LevelSizeFamilyUse
headline-display3.5remFraunces (serif)Hero titles
headline-lg2remFraunces (serif)Section headings
body-md1remInter (sans)Paragraph text
label-mono0.8125remJetBrains MonoTags, metadata, counts

Prose that goes with it: “Serif is display-only — never set body copy in Fraunces. Mono is reserved for tags, keyboard hints, and numeric metadata; it signals ‘machine-readable’ at a glance.”

4. Layout & spacing — one scale, no magic numbers

Define a single spacing scale and require everything to snap to it. This is the highest-leverage rule for making generated UI look intentional.

spacing:
  xs: 4px
  sm: 8px
  md: 16px
  lg: 24px
  xl: 40px
  "2xl": 64px
## Layout & Spacing
- 12-column grid, 1120px max content width, 24px gutters.
- All padding, margins, and gaps use spacing tokens — never arbitrary px.
- Breakpoints: sm 640, md 768, lg 1024, xl 1280.
- Default vertical rhythm between sections is `xl` (40px); `2xl` at page
  boundaries.

5. Elevation & depth

State the strategy, not just values. A dark-first, flat design might reject shadows entirely in favor of surface-color steps.

## Elevation & Depth
Depth is expressed through surface color, not shadow. A raised element moves
from `surface` to `surface-alt` and gains a 1px `border` hairline. Reserve
soft shadows for transient overlays only (menus, dialogs):
`0 8px 24px rgba(0,0,0,0.45)`.

6. Shapes — corner-radius language

rounded:
  sm: 6px    # inputs, tags
  md: 12px   # cards, buttons
  lg: 20px   # modals, hero panels
  full: 9999px  # pills, avatars

“Radius scales with the element’s size — small controls get sm, cards get md, full-bleed panels get lg. Never mix two radii on the same element.”

7. Components — recipes built from tokens

Each component is a small recipe that references tokens rather than restating values. This is where the tokens pay off: a component definition reads like a sentence.

components:
  button-primary:
    backgroundColor: "{colors.primary}"
    textColor: "{colors.on-primary}"
    typography: "{typography.label-mono}"
    rounded: "{rounded.md}"
    padding: "{spacing.sm} {spacing.md}"
    height: 44px
  card:
    backgroundColor: "{colors.surface-alt}"
    textColor: "{colors.on-surface}"
    rounded: "{rounded.md}"
    padding: "{spacing.lg}"
    border: "1px solid {colors.border}"
  tag:
    backgroundColor: "transparent"
    textColor: "{colors.muted}"
    typography: "{typography.label-mono}"
    rounded: "{rounded.sm}"
    padding: "{spacing.xs} {spacing.sm}"

Follow each with a line of prose: “Primary button has exactly one instance per view — it marks the single most important action. Everything else is a text or ghost button.”

8. Motion & easing

Motion is easy to omit and easy to get wrong, so make it explicit. Give durations, easing curves, and a rule for what animates.

## Motion & Easing
- Durations: fast 120ms (hovers), base 200ms (most transitions),
  slow 320ms (entrances/overlays).
- Standard easing: `cubic-bezier(0.2, 0, 0, 1)` (decelerate) for elements
  entering; `cubic-bezier(0.4, 0, 1, 1)` (accelerate) for elements leaving.
- Only animate `transform` and `opacity` — never `width`, `height`, or
  `top/left` (they thrash layout).
- Respect `prefers-reduced-motion`: drop all non-essential motion to a
  simple opacity fade.

9. Accessibility

Bake accessibility into the spec so agents treat it as a constraint, not an afterthought. State the concrete, checkable rules.

## Accessibility
- Body text meets WCAG AA: contrast ratio >= 4.5:1 against its surface;
  large text (>= 24px) >= 3:1.
- `primary` on `surface` is for accents and large text, not body copy —
  check contrast before using it for small text.
- Every interactive element has a visible focus ring: 2px `primary` outline
  with a 2px offset. Never remove focus outlines without a replacement.
- Hit targets are >= 44x44px.
- Color is never the *only* signal — pair it with an icon, label, or shape.

10. Do’s and Don’ts

Close with blunt, scannable guardrails. This section catches the failure modes prose elsewhere only implies.

## Do's and Don'ts
Do:
- Use `primary` for exactly one call-to-action per view.
- Reference tokens (`{colors.surface}`) — never hard-code hex or px.
- Keep the serif for display and the mono for metadata.

Don't:
- Introduce a second accent color.
- Use drop shadows for static elements (depth = surface color).
- Set body text in the serif or below 1rem.
- Mix two corner radii on one element.

Best practices

Semantic over literal names. primary, surface, on-surface, error describe roles and survive a redesign. amber-500, dark-bg describe values and lie the moment the brand shifts. Reserve literal scales (if you need them) as a lower layer that semantic tokens point at.

Keep it DRY with token references. Use the {path.to.token} syntax ({colors.primary}, {typography.label-mono}) so a value is defined exactly once. Components reference tokens; tokens don’t repeat values. One edit propagates everywhere.

Tokens carry values; prose carries intent. The YAML says what amber is; the Markdown says when to reach for it and when not to. Agents need both — values alone produce technically-correct but tasteless UI.

Version it. Put a version in the front matter and bump it on meaningful changes. The reference CLI can diff two versions to catch regressions and lint the file for broken references and failing contrast ratios, so treat design.md like code: review changes in PRs.

Put it where tools look. Save it as DESIGN.md in the repository root. Agents like Claude Code, Cursor, Kiro, and Windsurf pick it up from there without extra configuration. For a monorepo, a root file plus per-package overrides works; keep the root file authoritative.

How AI tools consume it. On a UI task, the agent reads DESIGN.md, resolves token references, and applies your colors, type, spacing, and component recipes to whatever it generates. Because the file is plain text in your repo, it travels with the code and updates through normal review — no plugin, no external service, no build step.

Starter template

Copy this, delete the comments, and fill in your own values:

---
version: 0.1.0
name: My Product
description: One line on the mood and the single defining visual move.
colors:
  primary: "#000000"
  on-primary: "#FFFFFF"
  surface: "#FFFFFF"
  surface-alt: "#F5F5F5"
  on-surface: "#111111"
  muted: "#6B6B6B"
  border: "#E4E4E7"
  error: "#E5484D"
typography:
  headline-display:
    fontFamily: 'system-ui, sans-serif'
    fontSize: 3rem
    fontWeight: 700
    lineHeight: 1.1
  body-md:
    fontFamily: 'system-ui, sans-serif'
    fontSize: 1rem
    fontWeight: 400
    lineHeight: 1.6
  label-md:
    fontFamily: 'ui-monospace, monospace'
    fontSize: 0.875rem
    fontWeight: 500
spacing: { xs: 4px, sm: 8px, md: 16px, lg: 24px, xl: 40px }
rounded: { sm: 6px, md: 12px, lg: 20px, full: 9999px }
components:
  button-primary:
    backgroundColor: "{colors.primary}"
    textColor: "{colors.on-primary}"
    rounded: "{rounded.md}"
    padding: "{spacing.sm} {spacing.md}"
---

## Overview
<!-- Mood, voice, the one defining move, and what to avoid. -->

## Colors
<!-- Semantic palette + when to use each. Light/dark if relevant. -->

## Typography
<!-- Families and the named type scale. Which face goes where. -->

## Layout & Spacing
<!-- Grid, max width, breakpoints, "snap everything to the scale". -->

## Elevation & Depth
<!-- Shadow vs. surface strategy. -->

## Shapes
<!-- Corner-radius language. -->

## Components
<!-- Per-component recipes referencing tokens. -->

## Motion & Easing
<!-- Durations, curves, what animates, reduced-motion. -->

## Accessibility
<!-- Contrast targets, focus rings, hit targets, non-color signals. -->

## Do's and Don'ts
<!-- Blunt, scannable guardrails. -->

References

All of the following were consulted while writing this guide. GitHub sources were fetched and verified directly; designmd.app and typeui.sh returned 403 to automated fetching, so their details here come from their public search-indexed descriptions rather than a direct page read.

Only the format is standardized; the values in this guide’s worked example are illustrative, not prescriptive. Adapt them to your own product.