Does generated design have to be average?

AnyPixel gives a coding agent a design position to build from, and a score it can read back. Everything it knows is a file in your tree.

Get started

Read the field notes →

A single line that tangles into a scribble and then resolves into one straight rule.

Every direction at once, then one. That is the whole argument.

You can tell on sight.

Ask a frontier model for a landing page and you get one. It is competent. It is plausible. And you can tell, on sight, that a machine made it.

The tells are always the same: a tinted icon chip, a glassmorphic card, a gradient heading, a uniform grid of identical boxes, and spacing that lands on 13px.

This is not ignorance. The same model will recite Rams' ten principles on request. It knows the rules. It does not build from them.

The problem is not that the model is bad at design. It is that, left alone, it lands every time on the mean.

Atlassian, testing portable design context in production, put it exactly.

"AI defaults to the average of everything it's trained on. Generic in, generic out."

Atlassian

Design quality is the residue of applied constraint. Averaging is the one operation guaranteed to destroy it.

So the answer is no. It takes two moves.

Displace the average with constraint that survives sampling.

Not "use good typography", which gets averaged away, but exactly two families, five sizes on a 1.25 scale, a measure of 45 to 75 characters, flush left.

Then give the model eyes.

A model cannot see its own output, but it can read a number with a file and line beside it, and that closes the loop.

Neither works alone. Constraints without measurement are ignored under pressure. Measurement without constraints only tells you which average you landed on.

The loop

  • Direct the agent by compiling law and lens into its context.anypixel context --lens rams --format prompt
  • Generate from that position instead of the corpus mean.
  • Measure the result in Chrome, scoring the rendered DOM rather than the source text.anypixel lint src/ --render
  • Correct from findings that come back with file, line, rule id and a positive replacement.

Then go again. The loop is bounded at three passes and does not count deleted content as progress.

Same content. Same measurement path. Two numbers.

5.1 / 10

examples/generic-ai-output. What a frontier model emits for "build me a landing page" with no design context.

10.0 / 10

examples/canon-vignelli. The same content, composed to the canon.

Each is a single HTML file, both scored --render --full-page against the foundation and the default doctrine with no lens, and test/run-all.sh pins the equal-path comparison so it cannot drift.

The averaged page fails WCAG at 2.54:1, breaks the type scale six times, lands 38% of its spacing off the scale, ships the full glassmorphism combination, and, rendered, uses 16 containers where the composed page uses 1.

The composed page's remaining 0.2 under the Vignelli lens is a true finding: its whitespace measures 0.66 against the lens's declared 0.45. The tool is right. The fixture is left as-is.

There is also a controlled comparison: four briefs, two arms. The blind arm got the brief and nothing else. The canon arm got the same brief plus 3.2 KB of lens context. Neither arm ran a linter.

6.18 → 8.02

Overall, across all four briefs.

−60%

Unstated-rule failures, on 33 of the 49 rules that never appeared in the context. 7.50 → 3.00 per page.

76 → 0

Rendered WCAG contrast failures on the blind pages.

Four briefs, one model family, no repeats, against no direction at all, the weakest baseline. Directional, not a study.

What is in the box

Everything AnyPixel knows is a file in the tree. Nothing is rented through a server.

  • Law. 49 rules across 7 domains, each carrying a machine-checkable assertion, a severity, a rationale and a positive replacement.
  • Lenses. 21 named positions, each grounded in a sourced study, each declaring what it is wrong for.
  • Scorer. Headless Chrome over the DevTools Protocol, one browser session per observation; what it cannot measure it reports as unmeasured.
  • Contract runner. Executes a Design Contract end to end and leaves a run directory with a manifest.
  • MCP server. On-demand rule access for an agent, reading the same files the CLI reads; every tool it offers is a CLI command.
  • Corpus. Curated surfaces in, percentile evidence out; it moves no threshold.

The law sits in three tiers: a fixed foundation of 5 rules that no doctrine or lens may relax, the 39-rule canon that carries the authored doctrine, and 5 dated drift rules that record what generation does this year and lose standing once reviewed.

At v0.2.0 that comes to 49 rules in 7 domains, 21 lenses drawn from 20 sourced studies, 53 test suites, and 0 npm dependencies.

A design decision has a record.

A Design Contract binds a brief, a position, the rules that apply, the gates that may stop a release and the people who may decide, in one versioned JSON file.

anypixel run executes it and leaves a run directory behind: findings, screenshots, a correction packet for the agent, an evidence report for the reviewer, and a manifest over all of it. Approvals sign the evidence digest.

RUN · canon-reference-page-v2 · 16 Sep 2026
VERDICT · PASS · every blocking gate passed and coverage met the threshold; awaiting the named approval
GATES · 4 · 3 BLOCKING · 4/4 PASSED · floor · render-agrees · position-held · geometry
CELLS · reference × desktop, mobile × light × default · COVERAGE 8/8
POSITION · vignelli · SELECTED BY HUMAN
APPROVAL · jh · EVIDENCE sha256 aa1904a1 · VALID

The reference contract already has a history. Version 1 failed: no breakpoint at 390px, and three columns collapsed to ten-character measures. The 45-character floor turned out to be a floor a phone cannot hold, since 390px minus two gutters holds 40 characters at 16px. Version 2 passed, with the rule declared out of scope at that viewport, the reason on the record and the threshold unmoved. Version 1's failing run is kept beside version 2's, because a contract line is a history and version 2 does not replace version 1.

What it declines to claim.

This is the part most tools leave out.

  • It measures roughly half of quality. Automatic GUI metrics explain up to 49% of variance in human aesthetic judgement, so a 10/10 means the work broke no law, not that the work is good.
  • It demoted its own measures. Six of them failed to discriminate, including the published academic model the composition domain was built on, which scored the averaged fixture higher than the composed one.
  • It withdrew a published result. An external validation cited for six days was a measurement of a browser error page, retracted in three documents on 26 August 2026 and not replaced, because choosing a substitute after the fact is post-hoc selection.
  • A lens can be wrong for a brief. Each declares what it is unfit for, anypixel fit refuses those, and Hara on a conversion page will lose you money.
  • No human study has run. The blind human rating that would let any of this claim more than conformance has not happened, so every number on this page is a conformance claim.

Clone it. Check the machine. Score a surface.

  • git clone https://github.com/justinrhowell/anypixelThe whole instrument is in the tree.
  • ./bin/anypixel doctorAsks whether this machine can produce a trustworthy result.
  • ./bin/anypixel lint src/ --lens rams --render http://localhost:3000Score your surface through a position, against the rendered DOM.

It needs Node 22+ and a Chrome installation for --render, with no npm install and no build step.

For an agent: claude mcp add anypixel, or load the skill in skills/anypixel/SKILL.md.

Get started