Design.md: how to describe a design system for AI agents
AI agents (Claude, GPT, Cursor) are increasingly writing UI code. But they have a fundamental problem: they don't know your design system. Every session starts from scratch. Every visual decision is a guess.
Design.md solves this. It's a structured design system specification that AI reads at the start of every session. Instead of guessing, it looks things up.
The problem: 200 reasonable guesses
When AI writes an interface, it makes hundreds of micro-decisions: what padding for a card, what shade of blue for a link, what border radius for a button. Each decision looks fine. But 200 “reasonable guesses” don't add up to a consistent design.
Hardik Pandya precisely describes three LLM limitations:
- Value fabrication. AI doesn't look up your tokens. It generates plausible ones. If the system has
--space-200= 8px, AI will writepadding: 12pxbecause 12 is a reasonable number. It's not wrong. It's just not yours. - No memory between sessions. Every new session starts from zero. AI doesn't remember that yesterday it used
#2563EBfor links. Today it picks a different blue. By the fifth session, you have three different blues in one prototype. - Can't read design intent from code. AI sees component APIs: import Button, pass
appearance="primary". But it doesn't understand when to use a modal instead of an inline message, or what spacing to put between sections. That knowledge lives in designers' heads.
What is Design.md
Design.md is a file in the repository root that describes your design system in a format suitable for AI. For Cursor, it lives in .cursor/rules/. For Claude, in CLAUDE.md. For any agent, in the session context.
The idea is simple: AI shouldn't decide “which blue to use for a link.” It should find var(--color-link) in the spec.
AirOps went further: their brand guideline has two representations: a live visual guideline for humans and a structured instruction for AI agents. One source of truth, two consumption formats.
What to include
Tokens
A complete map of CSS variables with values and context. Not just --color-primary: #2563EB, but when and where to use it:
## Colors
- `--color-text`: #171717 — primary text
- `--color-text-sub`: #525252 — secondary text, descriptions
- `--color-link`: #2563EB — links and interactive elements
- `--color-bg`: #fafafa — page background
- `--color-border`: #e5e5e5 — dividers and borders
## Spacing (base 4px)
- `--space-100`: 4px — minimum, between icon and text
- `--space-200`: 8px — inside component
- `--space-300`: 12px — between related elements
- `--space-400`: 16px — standard padding
- `--space-600`: 24px — between blocks
- `--space-800`: 32px — between sections
Components
For each component: when to use, when not to use, which tokens are involved, what states exist:
## Button
When: primary action on the page
When NOT: navigation (use Link)
Variants: primary | secondary | ghost
Sizes: sm (32px) | md (40px) | lg (48px)
Tokens:
- Background: var(--color-primary)
- Text: var(--color-on-primary)
- Border radius: var(--radius-md)
- Padding: var(--space-300) var(--space-400)
States: default, hover, active, focus, disabled
Patterns
Layout rules that AI can't derive from code: spacing between sections, grid behavior, responsiveness principles. This is what usually lives in designers' heads and is never written down.
Three-layer token architecture
Hardik Pandya proposes a three-layer structure that protects against drift:
- Upstream tokens from the design system:
--ds-text: #171717 - Project aliases with reference and fallback:
--color-text: var(--ds-text, #171717) - Components use only aliases:
color: var(--color-text)
The alias is a protective layer. If the upstream system renames a token, you change one alias. Dark theme, high contrast, any future theme: all resolve automatically through the chain.
Audit: catching what AI missed
Design.md gives AI the right answers. The audit script catches cases where AI guessed anyway. A simple script scans CSS files for hardcoded values and suggests the specific token:
src/components/Nav.css
L42: color: #2563EB → use var(--color-link)
L78: padding: 12px → use var(--space-300)
Errors: 2 | Warnings: 0
The script returns exit code 1 on errors and can be added to CI. Zero violations = safe to merge.
How to maintain
The spec lives in the repository next to the code, not in a Figma comment or Notion. When a component changes in a PR, the spec is in the same diff. Three rules:
- New component: write the spec before or during development
- Design system update: update the affected sections of Design.md
- Audit in CI: the script automatically checks every PR
A small accurate spec is better than a large outdated one.
Result
Your tenth AI session delivers the same visual quality as the first. AI doesn't guess, it looks up. Doesn't fabricate, it references. Doesn't drift, it gets checked by audit.
Design.md is not documentation. It's infrastructure.