Off-Brand UI From Your AI Agent? Write, Lint and Wire a DESIGN.md
Ask a coding agent for a settings page and you'll get something that works and looks almost right. The blue is a shade off. The font is close to yours but isn't. The cards have rounded corners your brand never uses. You
Ask a coding agent for a settings page and you'll get something that works and looks almost right. The blue is a shade off. The font is close to yours but isn't. The cards have rounded corners your brand never uses. You fix it, and the next screen has the same problems.
The agent isn't being careless. It has no reliable place to read your design system, so it fills the gaps with whatever is typical. Prompting harder helps for one screen. A file the agent reads every time helps for all of them.
That file is what DESIGN.md is for. It's an open format from Google Labs, published on GitHub under Apache 2.0, "for describing a visual identity to coding agents." This walkthrough writes a small one, lints it with the official CLI, fixes what the linter finds, and then makes sure your agent actually reads it.
One caveat up front: the format is at version alpha. The README says the spec, token schema and CLI "are under active development," so expect changes.
What goes in a DESIGN.md
A DESIGN.md has two layers:
-
Design tokens in YAML, either as front matter at the top of the file or as
yamlcode blocks inside each section. These are the exact values: colors, typography, spacing, corner radius, components. -
Markdown prose in
##sections that explains how to use those values.
The spec calls the tokens "the normative values" and says the prose "provides context for how to apply them." The project's philosophy page goes further and calls the prose "the most vital part of the specification."
That split is the whole idea. A hex code tells the agent what your accent color is. Only a sentence can tell it that the accent is for the primary button and nothing else.
Sections are optional, but the ones you include should follow this order: Overview, Colors, Typography, Layout, Elevation & Depth, Shapes, Components, Do's and Don'ts.
Step 1: Write a small one
Here's a deliberately small file for a made-up internal finance dashboard. Save it as DESIGN.md in the root of your repo.
---
version: alpha
name: Ledger
colors:
primary: "#14213D"
accent: "#2F6FFF"
surface: "#F5F7FA"
on-accent: "#FFFFFF"
typography:
heading:
fontFamily: Inter
fontSize: 2rem
fontWeight: 600
body:
fontFamily: Inter
fontSize: 1rem
rounded:
sm: 4px
spacing:
sm: 8px
md: 16px
components:
button-primary:
backgroundColor: "{colors.accent}"
textColor: "{colors.on-accent}"
rounded: "{rounded.sm}"
padding: 12px
---
## Overview
An internal finance dashboard for accountants who read numbers all day.
Calm, dense and precise, like a well-kept paper ledger. Nothing decorative.
## Colors
- **Primary** {colors.primary} carries all text and table rules.
- **Accent** {colors.accent} is only for the one primary action on a screen.
Never for links, icons, charts or highlights.
- **Surface** {colors.surface} is the page background, never pure white.
## Do's and Don'ts
- **Don't** add gradients, shadows or rounded cards.
- **Don't** use the accent for more than one element per screen.
- **Do** right-align every number column.
A few things worth noticing:
-
Components reference tokens with
{path.to.token}, sobutton-primarypoints at{colors.accent}instead of repeating the hex value. - The Overview names a specific thing ("a well-kept paper ledger") instead of a list of adjectives. The philosophy page argues this directly: "Adjectives describe a region. A specific reference describes a point." Words like "modern, clean, premium" give the agent nothing to aim at.
- The Do's and Don'ts are short and specific. The same page warns that a long, rambling list of don'ts is often a sign the description was too vague.
Step 2: Lint it
The official CLI is on npm as @google/design.md. You can run it without installing anything:
npx @google/design.md lint DESIGN.md
On Windows PowerShell, the README says the .md in the command name can clash with the Markdown file association. Use the dot-free alias instead:
npx -p @google/design.md designmd lint DESIGN.md
I ran the file above through version 0.4.0 of the CLI. This is the real output:
{
"findings": [
{
"severity": "warning",
"path": "components.button-primary",
"message": "textColor (#ffffff) on backgroundColor (#2f6fff) has contrast ratio 4.34:1, below WCAG AA minimum of 4.5:1.",
"rule": "contrast-ratio"
},
{
"severity": "info",
"message": "Design system defines 4 colors, 2 typography scales, 1 rounding level, 2 spacing tokens, 1 component.",
"rule": "token-summary"
}
],
"summary": {
"errors": 0,
"warnings": 1,
"infos": 1
}
}
I didn't plan that warning. White text on that bright blue looks fine on a good screen, but it falls below the WCAG AA minimum of 4.5:1 for normal text. Without the check, every primary button the agent builds would have carried the problem.
The linter has eleven rules. The ones you'll hit most often:
-
broken-ref(error): a{colors.something}reference that points at nothing. -
contrast-ratio(warning): a component's text and background colors fall below 4.5:1. -
missing-primary(warning): colors are defined but there's noprimary, so agents will invent one. -
missing-typography(warning): colors but no type tokens, so agents will use default fonts. -
section-order(warning): sections out of the canonical order.
Errors make lint exit with code 1, so you can use it in CI. I checked this with a typo: changing the reference to {colors.acent} produced a broken-ref error ("Reference {colors.acent} does not resolve to any defined token.") and exit code 1. Warnings alone still exit with 0, so if you want contrast problems to block a merge, read the JSON and fail on warnings yourself.
Step 3: Fix it and check the change
I darkened the accent to #1F5AE6 and saved the result as DESIGN-v2.md. Lint now reports zero errors and zero warnings. To see exactly what changed between the two versions, use diff:
npx @google/design.md diff DESIGN.md DESIGN-v2.md
The output lists accent under modified colors and button-primary under modified components. It also shows warnings going from 1 to 0 and "regression": false. diff exits with 1 when the new file has more errors or warnings than the old one. That makes it a cheap guard on pull requests that touch the design file.
Before you pick a fix, read the prose again. Your rule says the accent is for the primary action, so changing its shade is a brand decision, not just a lint fix. The linter tells you there's a problem. Choosing the answer is still your job.
Step 4: Make sure your agent reads it
A file in your repo helps only if the agent loads it. Nothing in the sources I used says that coding agents pick up DESIGN.md automatically, so point to it from the instruction file your agent already reads.
Claude Code. CLAUDE.md supports imports with @path/to/file. According to the Claude Code memory docs, imported files are "expanded and loaded into context alongside the CLAUDE.md that references them." Adding @DESIGN.md loads it in every session. The same docs note that imports don't reduce context cost. So if most of your sessions aren't about UI, a one-line pointer is lighter:
## UI work
Before creating or changing any UI, read DESIGN.md and follow its tokens and its Do's and Don'ts.
Cursor, Codex and other agents that read AGENTS.md. Put the same pointer in AGENTS.md. If you're not sure which instruction files your agent loads, A Stray AGENTS.md Can Steer Your Agent: Check What It Loads First shows how to check. And if your CLAUDE.md is already long, Your CLAUDE.md Is Too Long covers what to cut first.
The spec itself. npx @google/design.md spec prints the format specification. The README describes it as "useful for injecting spec context into agent prompts." That helps when you ask an agent to write or extend the DESIGN.md for you.
Then test it the way you'd test any instruction: ask for one screen and check three things. Is the accent used only once? Are the corners 4px? Are the number columns right-aligned? If not, the prose is usually too vague, and the fix belongs in the file, not in your next prompt.
Quick checklist
- [ ] DESIGN.md in the repo root with a
primarycolor and typography tokens - [ ] Components reference tokens with
{...}instead of repeating values - [ ] Overview names one specific reference, not a list of adjectives
- [ ] Every color has a sentence saying where it goes and where it doesn't
- [ ] Short, specific Do's and Don'ts
- [ ]
lintshows zero errors, and every warning has been read - [ ]
diffrun on any change to the file - [ ] CLAUDE.md or AGENTS.md points to DESIGN.md
- [ ] One test screen checked against the rules
Where to go next
- DESIGN.md Quick-Start Cheat Sheet (Free): six pages to keep next to your editor. It covers the two-part anatomy, why prose carries the rules, a complete annotated example with weak and strong prose side by side, and the CLI and built-in contrast checks.
- DESIGN.md: The Complete Guide to Design Systems for AI Agents: the full reference. It covers the token schema, lint, diff and export (Tailwind v4 and W3C DTCG), wiring it into Claude Code, Cursor, Kiro and Windsurf, the eight most common mistakes, and a walkthrough that builds a design system from scratch.
This article was written with the assistance of AI and reviewed by the author.
Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.