unvibed.
Menu
Free UI audit

Field notes / 02

DESIGN.md for Claude Code and Cursor: how to make your agent stop guessing your UI

Build a small, inspectable design contract from a screen you already trust.

Unvibed ·

Picture a settings screen with three different blues. The save button uses a Tailwind class, the active tab uses a CSS variable, and a hand-written link uses a hex value. An agent asked to add a fourth control can make a plausible choice from any of them. Telling it to “follow the design system” has little value when the project presents three systems and never says which one owns an action. A useful DESIGN.md settles that decision and points to the code that implements it.

Start with a screen you would willingly keep. In our client portal, a proof, a review state and a due date belong together. That relationship gives the design work a purpose: a client should know which proof to open. It is a better starting point than asking a model to choose a mood. If no screen is good enough to keep in full, choose one piece, perhaps the invoice row or the type used on a printed statement. Write down precisely what you want to retain about it.

Read the project before writing a rule

Open the stylesheet that is actually loaded on the selected route. Follow its imports. Check the layout for font imports, the Tailwind theme if present, and the sources of the button, input and list item on screen. A token in an unused file is evidence of an intention, not of current behavior. Inspect the computed style of the primary button at rest and with focus. Compare the computed value with the declaration you found. Save both file names in your notes.

Repeat that for a heading, a regular paragraph, a secondary label and a repeated row. You are looking for a few patterns rather than a complete inventory of every pixel. A single unusual margin may have a reason: it could align a label with the optical edge of an icon. Five near-identical margins from unrelated components probably want one shared role. Keep observations separate from decisions until you know which category you are looking at.

Check how the project loads its fonts. A font family in CSS does not guarantee that the face ships. A screenshot taken before the font finishes loading can make the body look heavier or the heading narrower than intended. Locate the local file or package, the available weights and the fallback stack. If the app depends on a remote font that fails offline, include the fallback in your review. The fallback has to fit the same form at phone width.

Give the agent a contract it can parse

Google’s DESIGN.md specification pairs named values with prose about how to use them. The file is a convenient place for a product name, colors, typography and other supported token groups. The prose carries what a value cannot express: when a status turns urgent, which part of a row takes priority, and where a display face would slow down reading. Use the specification for the keys and examples rather than inventing a private format with a familiar name.

Write the smallest set of roles that describe the selected screen. Useful color roles include page, surface, primary text, secondary text, action, text on action, focus and error. Name success or warning if the app uses them. If a token means “amber,” you have described what it looks like today. If it means “pending review,” you have described the choice another engineer must make when implementing tomorrow's proof list. Neither naming style excuses an unreadable foreground.

Choose six type steps that you can explain. In a dense work app you might reserve the largest step for the page title, the next two for sectional headings, one for item titles, one for body and one for labels. A marketing page might give more space to its headline. Write a real use beside each step. Include line heights and weights, and look at a long title. Six roles do not mean that every screen needs six visibly different sizes.

Connect the written choices to CSS

The CSS file is the implementation. Put the chosen roles into custom properties and use the existing theme entry point to load them. If Tailwind is already responsible for colors, bridge its theme to those values. Adding a second independent palette creates the same guessing problem a second time. Check a rendered button after wiring the import. A successful build cannot tell you whether an old class still overrides the role.

An eight-point spacing scale is useful when it describes relationships. A compact form might put eight pixels between a label and its input, sixteen between controls and thirty-two between sections. Write those relationships down, then compare them with the existing screen. Keep a justified exception for a hairline, an optical offset or a compact icon. An eight-point scale is not an instruction to round the thickness of a border up to eight pixels.

For a mobile view, keep the role and adjust the composition. The page title can use the same heading role without taking the same number of lines. A row that places the due date at the far right on desktop may put it under the proof title on a phone. The token file cannot make that decision for a component. Include one sentence about reading order and test a long date. You want the same information to survive the change in width.

Check color pairs as they are used

Text contrast is a relationship between foreground and background. Recording a color as accessible on its own is meaningless. Check primary and secondary text on both page and surface, button text on action, and error text where the error actually appears. For normal text the AA contrast threshold is 4.5 to one; large text has a different threshold. For non-text controls check the applicable contrast requirement and the adjacent background. The WCAG contrast guidance explains the exceptions and definitions.

Consider a pale accent that looks attractive on paper. It might work as a selected row background under dark text and fail as small text on white. Keep the successful pairing and change the failing one. Check the rendered result when an overlay or opacity changes the effective background. Write down the measured pair and role instead of claiming that the entire product is WCAG compliant. A contrast pass says nothing about whether a dialog traps focus or a save button has a useful name.

Make the rule appear in the next session

Put a short instruction in the project's CLAUDE.md and AGENTS.md: read DESIGN.md before changing UI, follow its roles and check the affected route. Preserve any existing project instructions. A second run should not append the same rule twice. In a nested repository, say which design file applies to the app you are changing. An absolute path on one developer's computer will fail on the next person's machine.

For Cursor, point the project's applicable Cursor rule at the same file or explicitly attach DESIGN.md to the task. Do not assume an agent loaded a document because it exists on disk. Open a fresh session and ask which role it would use for a secondary label and where the role is defined. A useful answer names the file and an actual value. A vague answer about consistency is a reason to check the instruction path before letting the agent edit several screens.

Give the contract one real job

Try a small request: add the client's due date below a proof title. Ask the agent to reuse the row component, choose an existing text role and preserve the approval action. Review its diff. A good result references an existing token, fits on a narrow screen and leaves the route's behavior alone. An invented utility value is a chance to ask whether the contract is missing a role or the implementation ignored one.

Now try the same request on a less tidy route. If applying the rule would silently change half the product, narrow the scope. Keep the token file global if appropriate, but migrate one component at a time. Note which screens still use the old values. A documented migration is more truthful than a claim that all surfaces already use the new system. The next person needs to know where the contract is an intention and where it has been verified.

Try the same supposed default on two unrelated products. Tallybook needs comparable invoice amounts and a visible exception. Its Utility direction gives those fields a tight shared grid. Folio needs a client to spend time with a proof before deciding whether to approve it. Quiet luxury gives the work room and keeps the review action in context. A design brief earns its name when it explains why those choices differ. Compare the direction studies.

In the real-repo trial for design client portal, the plain agent won in both orders. The two votes were 1 and 2 on a seven-point scale oriented toward the kit, with four neutral. The hand-designed Folio example is a separate illustration; the trial compares two agent edits of the original app.

Before writing a design document, run the free audit on one route and identify a choice your current instructions leave open. Use that decision to write the first rule in DESIGN.md. A useful rule names a component, its purpose, its visual values and the working behavior an editor needs to preserve.