AI agents
How to write a design manual your coding agent and audits can enforce
Turn brand guidelines into rules a coding agent can follow and an audit can check: exact tokens and thresholds, with a check and exceptions for each rule.
A design manual a coding agent can follow is a short file of exact values and testable rules, not a brand book. Each rule names what it applies to, the allowed value or threshold, how to check it, and its exceptions.
Keep the file in the repository, point your agent’s instructions file at it, and check the deployed site against the same rules. Then the manual, the code and the site can be compared, and drift shows up as a failed check instead of a feeling that the site looks off.
This is the standing-rules part of fixing issues with AI coding agents.
Why brand guidelines fail agents
Brand guidelines are written for people who already share the context: “clean and modern”, “generous whitespace”, “use the accent sparingly”. A designer reads them and knows what to do. An agent reads them and guesses, differently in each session.
Anthropic’s documentation for Claude Code says it plainly: CLAUDE.md is context, not enforced configuration, and instructions work best when they are “concrete enough to verify”. The same holds for Cursor’s rules and for AGENTS.md. A rule the agent can verify is also a rule you can verify afterwards, which is the point.
- Use plenty of whitespace and keep the buttons on brand.- Padding, margin and gap use the spacing scale: 4, 8, 16, 24, 32px. Check: computed padding and gap values are 0px, normal or one of them.- Primary buttons have background primary (#0B57D0) and text on-primary. Check: computed background-color of .button--primary is rgb(11, 87, 208). Except: destructive actions use .button--danger.The testable rule pattern
Write every rule in four parts:
- Rule: what it applies to and what must be true. “Body text is at least 16px.”
- Value: the exact token, number or list. Not “large enough”, but 16px; not “brand blue”, but
primary,#0B57D0. - Check: how a person, a linter or a browser confirms it. “Computed
font-sizeofmain pis at least 16px.” - Exceptions: where the rule does not apply, named precisely. “Except
.fine-print, which may be 14px.”
The check line does most of the work. It forces the value to be measurable, it tells the agent how to test its own change, and it is the line your tests and audits turn into code. Write it in terms of what the browser reports: computed values, attributes and element counts. A rule that cannot get a check line is a judgment, and judgments go in a section a person reviews.
The exceptions line stops the agent from “fixing” deliberate choices. Without it, an agent asked to tidy the footer may raise the legal small print to 16px.
DESIGN.md and other formats
Any Markdown file works, but one format is designed for this job. On 21 April 2026 Google open-sourced the draft specification of DESIGN.md, the format its Stitch design tool uses, so that other tools can read it. Its repository lists the format at version alpha, still under active development. A DESIGN.md has two layers:
- YAML front matter with tokens:
colors,typography,rounded,spacingandcomponents, where a component refers to other tokens as{colors.primary}. - Markdown sections in a set order, any of which may be left out: Overview, Colors, Typography, Layout, Elevation & Depth, Shapes, Components, and Do’s and Don’ts.
The project’s command-line tool has a lint command that, among other things, flags token references that point nowhere and component colour pairs below WCAG’s 4.5:1. It is a draft from Google, not a W3C Standard.
If your tokens already live in code, as CSS custom properties or in the W3C Design Tokens Community Group’s JSON format, keep that file as the source of truth and make the manual name it. Two copies of the same values drift as surely as a site does, so add the rule that both change in the same pull request.
A DESIGN.md template
This template follows the DESIGN.md layout. The accessibility rules are not a separate section: each sits next to the token it constrains, with its WCAG criterion and the ratio we computed for each colour pair, rounded down. Replace the values with your own, and recompute every ratio when you do.
---version: alphaname: Example Shopdescription: Visual rules for example-shop.com. Change a value here and in src/styles/tokens.css in the same pull request.colors: primary: "#0B57D0" primary-hover: "#0842A0" on-primary: "#FFFFFF" ink: "#1A1C1E" muted: "#5C6066" surface: "#FFFFFF" surface-subtle: "#F3F4F6" border-control: "#8A8F98" error: "#B3261E"typography: h1: fontFamily: Inter fontSize: 32px fontWeight: 700 lineHeight: 1.2 h2: fontFamily: Inter fontSize: 24px fontWeight: 700 lineHeight: 1.25 body: fontFamily: Inter fontSize: 16px fontWeight: 400 lineHeight: 1.5 label: fontFamily: Inter fontSize: 14px fontWeight: 600 lineHeight: 1.4rounded: sm: 4px md: 8pxspacing: xs: 4px sm: 8px md: 16px lg: 24px xl: 32pxcomponents: button-primary: backgroundColor: "{colors.primary}" textColor: "{colors.on-primary}" typography: "{typography.label}" rounded: "{rounded.md}" height: 44px button-primary-hover: backgroundColor: "{colors.primary-hover}" textColor: "{colors.on-primary}" input: backgroundColor: "{colors.surface}" textColor: "{colors.ink}" typography: "{typography.body}" rounded: "{rounded.sm}" height: 44px---## OverviewExample Shop sells furniture online. The interface is quiet: one actioncolour, one typeface, generous space. Every rule a browser or alinter can confirm says how to check it; the rest are for review.If a task needs a value or a component this file does not list, stopand ask. Do not add one.## Colors- Text is ink or muted, on surface or surface-subtle. Check: computed color of text is rgb(26, 28, 30) or rgb(92, 96, 102). Except: text on primary is on-primary, links are primary, and error messages are error. Why: on surface, ink is 17.09:1, muted 6.32:1, primary 6.38:1 and error 6.53:1; on surface-subtle, ink is 15.52:1, muted 5.74:1, primary 5.80:1 and error 5.93:1. WCAG 1.4.3 asks 4.5:1.- Text on primary or primary-hover is on-primary (6.38:1 and 9.14:1).- primary marks actions: buttons and links. Never use it for decoration.- Fields sit on surface only, with a border-control border: 3.24:1 on surface, where WCAG 1.4.11 asks 3:1, but 2.95:1 on surface-subtle. Check: computed border-top-color of text inputs, select and textarea is rgb(138, 143, 152).- An invalid field shows a text error message next to it, tied to the field with aria-describedby, and has aria-invalid="true". Colour is never the only signal (WCAG 1.4.1, 3.3.1).- Component styles never contain a hex value; they use the tokens in src/styles/tokens.css. Check: Stylelint color-no-hex passes. Except: the tokens file itself.## Typography- One family: font-family: Inter, with system-ui as the fallback. Check: computed font-family of text starts with Inter.- Sizes are only those in the typography tokens: 32, 24, 16 and 14px. Check: every computed font-size of text is one of them.- Body text is at least 16px with a line height of 1.5. Check: computed font-size of main p and main li is at least 16px, and their computed line-height is 1.5 times it (24px at 16px). Except: .fine-print, which may be 14px.- Buttons and fields use the type tokens, not the browser's control font. Check: no button, input, select or textarea computes to 13.3333px.## Layout- Padding, margin and gap use the spacing scale: 4, 8, 16, 24, 32px. Check: computed padding and gap values are 0px, normal or one of them. Margins are checked in the source, because the browser reports an auto margin in pixels.- At a 320px-wide viewport the page does not scroll sideways (WCAG 1.4.10). Check: documentElement.scrollWidth is not larger than its clientWidth. Except: content that needs two dimensions, such as a data table or a map, may scroll inside its own container.- The sticky header never hides any part of a focused control; WCAG 2.4.11 fails only when it is hidden entirely; 2.4.12 asks this at AAA. Set scroll-padding-top to the header's height. Check: after each Tab, the focused element's top is below the header's bottom.## Shapes- Buttons use rounded.md, fields rounded.sm. No other radius. Check: computed border-radius of .button is 8px, of input 4px.## Components- button-primary: one per view, for the main action. At least 44px tall, with 16px side padding; the height, not the padding, sets its vertical size. States: default, hover, focus, disabled, loading.- No control is smaller than 24 by 24px (WCAG 2.5.8). Except: links inside a sentence, and controls 2.5.8's spacing exception covers. Check: the bounding box of every button, input, select and textarea is at least 24 by 24px.- Focus, on every interactive element: a 2px solid ring in primary, 2px outside the element. primary is 6.38:1 on surface and 5.80:1 on surface-subtle, above the 3:1 of WCAG 1.4.11. Never remove the browser's focus indicator without this replacement (WCAG 2.4.7). Check: on keyboard focus, computed outline-style is solid, outline-width 2px, outline-color rgb(11, 87, 208) and outline-offset 2px.- input: a visible label above the field. A placeholder is not a label (WCAG 3.3.2). Check: every input has a label element tied to it with for and id, or wrapped around it.## Do's and Don'ts- Do reuse a component before you create one.- Do ask before you add a token, a font or a component.- Don't change visible copy in a design task.- Don't use primary for headings, icons or illustrations.A few choices in it are worth copying even if you change everything else:
- Every colour pair the template allows has its ratio. The agent does not need to compute contrast to stay inside the pairs you already checked, and you can see at a glance which combinations exist. Our post on WCAG’s contrast thresholds for text and controls explains the numbers.
- The focus style is a rule, with its contrast. An agent asked to match a design “without the blue ring” has a written reason not to remove it.
- Target size has two numbers. 44px is the system’s choice; 24 by 24px is the size WCAG 2.5.8 asks at Level AA, with exceptions such as spacing and links in a sentence, which our post on target size and its exceptions covers.
- “Stop and ask” is a rule. Without it, an agent that cannot find the value it wants may simply add one, and the system has a new colour nobody chose.
Wire it into your agent
A manual the agent never opens does nothing. Each tool has a way to load it.
Claude Code. A CLAUDE.md file can import another file with @path, and the imported file loads into context with it:
## Design@DESIGN.md- Read DESIGN.md before any change to components, pages or styles.- Use the tokens in src/styles/tokens.css. Never type a colour, font size, spacing or radius value that DESIGN.md does not list.- If the task needs a value or a component DESIGN.md does not have, stop and ask.- Before you say a UI task is done, run `npm run lint:css` and `npm run test:design` and report both results.An import does not make the context smaller: the whole manual loads in every session. Anthropic suggests keeping each CLAUDE.md under 200 lines, so keep the manual short, or move it into a path-scoped rule under .claude/rules/ that loads only when Claude works with your UI files. Our guide to fixing WCAG issues with Claude Code sets up the rest: the check command and a project skill.
Cursor. Put the instructions in a project rule, an .mdc file in .cursor/rules/, with globs for your UI files. Cursor’s documentation says a file you mention with @ in a rule tells Agent where to look, and Agent reads it with its tools when it needs the content; it is not pasted into the prompt. So keep the rules that must always apply in the rule body itself, and mention @DESIGN.md for the full token list. The accessibility project rule for Cursor shows the frontmatter.
Other agents. Several agents read AGENTS.md, Cursor among them. Put the same instructions there and name the file by path. Recent versions of Claude Code read an AGENTS.md only when the project has no CLAUDE.md; if you keep both, put an @AGENTS.md line in the CLAUDE.md, and a team on several tools can keep one file.
Make every rule checkable
Each check line belongs to one of four layers. Sort them before you write any test:
- Source rules, for a linter. “No hex value outside the tokens file” is Stylelint’s built-in
color-no-hex, switched off for the tokens file with anoverridesentry. It runs in the editor, in the agent’s own check and in CI. - Computed values, for a browser. Font sizes, colours, radii and spacing as rendered. A short Playwright test reads them with
getComputedStyle()on one page per template; our UI audit post has a rule file in this form. - Behaviour, for component and accessibility tests. A label tied to its field, an error not shown by colour alone, a focus ring that appears. See the four layers of accessibility checks during development.
- Judgment, for a person. “One primary button per view” and “quiet interface” need someone who understands the page. Keep them in the manual, and in the reviewer’s list, not in a test.
Then close the loop on the deployed site. Tests run on fixtures and preview builds; your visitors get what the CMS, third-party scripts and last-minute overrides make of it. Read the rendered values there and compare them with the manual: our guide to checking your live site against your own design rules has a script that lists them per template.
Keep the manual in step
- One change, one pull request. A token value changes in the tokens file and in the manual together, or the agent follows the old one.
- Date the manual. A line at the top with the last change helps a reviewer see when a rule is older than the component it describes.
- Add rules from real drift. When an audit of the live site finds a value that should not exist, write the rule that would have caught it, in the manual and in the tests.
- Delete rules nobody can check. If a rule has had no check line for months, it is guidance; move it to the Overview or drop it.
Frequently asked questions
What is DESIGN.md?
A Markdown file format for describing a design system to coding agents: tokens for colour, type, radius, spacing and components in YAML, usually as front matter, then sections of written rules. Google open-sourced its draft specification, from its Stitch design tool, in April 2026. It is at version alpha and is not a W3C Standard.
What should a design manual for an AI coding agent contain?
Exact token values, and rules written in four parts: what the rule applies to, the allowed value or threshold, how to check it, and its exceptions. Put the accessibility thresholds next to the tokens they constrain, such as the contrast ratio of each colour pair and the minimum target size, and tell the agent to stop and ask when a value is missing.
How do I make Claude Code follow my design system?
Import the manual into CLAUDE.md with an @DESIGN.md line, or move it into a path-scoped rule in .claude/rules/ that loads only when Claude works with your UI files, and add a few rules: use only the listed tokens, ask before adding a value, and run the lint and design checks before saying a task is done. Instructions are context, not enforcement, so check the result too.
Should a design manual replace my design token files?
No. If your tokens already live in code, keep that file as the source of truth and have the manual name it. When both hold values, change them in the same pull request, or one of them drifts.
How do I check that a coding agent followed the design manual?
Sort the manual's check lines into four kinds: a linter for source rules such as no hex values in components, a browser test for computed values, component and accessibility tests for behaviour, and a person for judgment. Then compare the deployed site's rendered values with the manual, since tests run on preview builds, not on what visitors get.