A DESIGN.md Should Be a Full Spec, Not a Mood Board

James Phoenix
James Phoenix

If you cannot delete the CSS and regenerate it from the doc, you do not have a design spec. You have a mood board with extra steps.


The Doc That Made Me Rethink Design Docs

I was reading through HeyGen’s HyperFrames repo, an open-source tool that turns HTML, CSS, and animations into deterministic MP4s, and the file that stopped me was not the source. It was the DESIGN.md.

Most design docs I have written and most I have read are vibes. “Clean, modern, deep navy background, premium feel.” That sentence describes a thousand different interfaces. It is an adjective pile. Hand it to two designers and you get two products. Hand it to two agent runs and you get two products plus a fight.

The HyperFrames DESIGN.md is the opposite. It is roughly 1,850 words and 420 lines of pure specification. Eleven sections: color palette split into light and dark modes, each with accent colors and syntax highlighting; typography with font families, a Google Fonts import, and a full type scale; spacing tokens; border radius values; shadows and effects; a Mintlify config block; component patterns for cards, buttons, terminals, and badges; animation guidelines; brand assets. There is almost no prose. It is tokens and code.

The level of detail is the whole point. It does not say “use a green accent.” It says:

--accent-green-light: rgba(26,122,10,0.07) — Green badge backgrounds

It does not say “headings should be large.” It says:

H1: clamp(2.6rem, 6vw, 4.5rem) / Weight 400 / Letter Spacing -0.02em / Line Height 1.0

It does not say “cards have a subtle border.” It ships the rule:

.card { background: var(--surface); border: 1px solid var(--border); border-radius: 12px; }

That is not documentation about the design. That is the design, in a form precise enough to compile. The CSS in the repo is downstream of this file. You could throw the stylesheet away and an agent would rebuild it from the doc without guessing.

A Spec Is Anything Two Implementers Converge On

Here is my working definition. A spec is any artefact precise enough that two independent implementers produce the same thing. By that test, adjectives are never specs and tokens almost always are.

“Modern and clean” does not converge. Ten people read it ten ways. rgba(26,122,10,0.07) converges. There is exactly one color. clamp(2.6rem, 6vw, 4.5rem) converges. The math is the math. The HyperFrames doc passes the convergence test on every line, which is why I would call it a full spec and not a style guide. A style guide persuades. A spec removes choices.

This matters more than it used to because of who the reader is now. HyperFrames literally tags itself “built for agents.” The reader of that DESIGN.md is a coding agent rendering HTML to video, and an agent cannot infer “our green” from brand osmosis the way a designer who has sat in the company for a year can. The agent needs the green as data. Every adjective you leave in a design doc is a degree of freedom you have handed to a stochastic process. Every token you write is a degree of freedom you have taken back.

Detail Turns Styling From Invention Into Projection

This is the same lesson as my semantic triangle, just applied to the visual layer. When I give an agent a generic prompt, it invents three things at once: the product, the domain, and the implementation. The fix is to arrive with the ambiguity already removed, so the agent does projection instead of invention.

A detailed DESIGN.md is the visual corner of that triangle. Without it, “make the card look nice” is an invention task, and the agent invents a card by averaging its training data, which is how you get the generic AI aesthetic everyone can now smell. With the token block in hand, “render this card” is a projection task. The agent is not deciding what nice means. It is copying border: 1px solid var(--border); border-radius: 12px into place. Projection is the kind of task modern agents are extremely good at. Invention is where drift lives.

The detail is not bureaucracy. The detail is the friction that stops bad output before it starts. The doc that looks like overkill is the doc that makes your prompts shorter, because you stop writing paragraphs trying to pin down taste in English and start pointing at a file that already encodes it.

Leanpub Book

Read The Meta-Engineer

A practical book on building autonomous AI systems with Claude Code, context engineering, verification loops, and production harnesses.

Continuously updated
Claude Code + agentic systems
View Book

I Already Do This and Did Not Call It a Spec

The thing that made this click is that I have been running my own version for months without naming it. My skills/html-css-visual-qa/SKILL.md holds two locked image recipes: the warm-paper article diagram style and the dark-neon featured-cover style, with exact background treatments, glow colors, grid motifs, and a post-generation QA loop. The instruction in this very knowledge base is blunt about it: do not improvise style, that skill is the single source of truth.

That is a DESIGN.md by another name. The reason I locked it down is the reason HyperFrames locked theirs down. The moment style lives in my head instead of in a file, every generation is a fresh negotiation and the output wanders. The moment it lives in a precise artefact, every generation is a projection and the brand holds across hundreds of runs and across different models. The doc is what makes the visual identity a system instead of a streak of good prompts.

What Goes In, And The Test For Whether It Belongs

Concretely, a DESIGN.md earns the name when it carries:

  • Exact values, not ranges. Hex with alpha, clamp scales, pixel spacing tokens, radius values. If a range is unavoidable, give the range and the default.
  • Component-level rules as code. Not “buttons are rounded.” The actual CSS for the button, the card, the badge, the terminal chrome.
  • Config it depends on. The HyperFrames doc inlines its Mintlify JSON and points at where the CSS variables live. The spec is useless if the wiring is implicit.
  • The why for non-obvious choices. HyperFrames states it favors borders over shadows. That one sentence stops an agent from reintroducing shadows every refactor, the same way a non-goal in a backend spec stops scope creep.

The test for any line: could an agent, given only this file, regenerate that part of the system and land in the same place? If yes, it belongs and it is doing spec work. If it is an adjective that two readers would interpret differently, it is mood-board residue. Cut it or convert it into a token.

A DESIGN.md is not a smaller, fluffier cousin of the architecture doc. Done right, it is the same kind of object pointed at pixels instead of state machines. It is a contract. The HyperFrames one is worth reading precisely because it refuses to be anything less.


Related

Topics
Code Driven DesignCss RegenerationDesign DocumentationDesign SpecificationHtml Css Integration

Newsletter

Become a better AI engineer

Weekly deep dives on production AI systems, context engineering, and the patterns that compound. No fluff, no tutorials. Just what works.

Join 306K+ developers. No spam. Unsubscribe anytime.


More Insights

Cover Image for Fast Playwright E2E Without the Bloat

Fast Playwright E2E Without the Bloat

Most end-to-end suites die the same way. They start fast, then they bloat. A run creeps from forty seconds to four minutes. A few specs go flaky, so someone bumps the retries. The retries hide the fla

James Phoenix
James Phoenix
Cover Image for Write the Pseudocode, Let the LLM Type

Write the Pseudocode, Let the LLM Type

I asked Codex to “build a worker.”

James Phoenix
James Phoenix