Skip to content

Visual acceptance is a gate between intent.md and frontend code. An agent turns the intent into an inspectable mock, a named product or design owner signs a versioned acceptance.md, and the built screen is later checked against the accepted frames with screenshots and a separate review pass. A mock changes in minutes; a merged screen does not.

This page is for the developer who builds user interfaces with Claude Code, Codex, or Cursor, and for the tech lead who wants that loop to look the same across a team. The situation it fixes: you ask the agent for a settings screen, it ships a polished page in 20 minutes, and the product review sends it back because the hierarchy is wrong, the error state is blank, and nobody agreed on the mobile layout. If you do not have an intent.md yet, start with Plan: capture intent.md.

Scorecard Q7: How do you prototype and validate user interfaces before implementing code?

Max-score answer: a visual prototype loop, in which intent.md produces an inspectable mock through an approved design tool, iterated before code generation.

What you’ll walk away with from visual acceptance

Section titled “What you’ll walk away with from visual acceptance”
  • A way to pick the mock medium (Figma frame, repository HTML prototype, generated image, or fixture route) by the design risk you need to retire
  • Setup for design input in Claude Code, Codex, and Cursor, with the Figma and Playwright MCP servers where they help
  • Three copy-paste prompts: propose directions, build the inspectable prototype, and compare the implementation with the accepted frames
  • An acceptance.md template with states, breakpoints, criteria, approver, and date
  • A verification path that proves the built screen matches the mock without anyone reading the component code
  • The failure modes of agent-made mocks, and how to recover from each

For large, multi-screen work, this single artifact grows into the four-artifact design-to-code pipeline. This page is the lightweight version that earns the Q7 maximum on everyday features.

The developer scorecard awards zero to three points. Each step adds something a person other than the agent can inspect.

PointsYour answer todayThe next move
0No visual prototyping; code goes straight into frontend filesFor the next UI change, ask the agent for a mock before any component code
1Static screenshots pasted into chat as one-off referencesSave the references in design/<feature>/ so the next session and the reviewer see the same input
2Figma designs inspected through the Figma MCP server or image attachmentsAdd the missing half: states, breakpoints, and a named approver recorded in acceptance.md before code starts
3intent.md produces an inspectable mock through an approved design tool, iterated before code generationKeep it honest: check the implementation against the accepted frames with evidence, not by eye

Pick the cheapest medium that answers the question you are unsure about. A mock that looks finished but answers the wrong question is the most expensive option.

MediumAnswersWeak atUse when
Figma frame, read through the Figma MCP serverDesign-system fit: components, tokens, spacingReal interaction; seat limits on some plansYour team designs in Figma and the frame already exists
HTML prototype in the repository, built from your real tokensInteraction, focus order, responsive behaviourPixel polish; it is thrown awayThe risk is how the screen behaves, not how it looks
Generated image (Codex image_generation, any image model)Visual direction and hierarchyEverything else: text, states, feasibilityYou need three different directions in minutes, before anyone commits
Fixture route inside the app (/prototype/...)High fidelity with real componentsCost; it drifts toward production codeThe screen is mostly existing components in a new arrangement

A generated image is a direction, never the accepted artifact. Its text is often wrong and its components rarely exist in your design system, so accept an HTML prototype or a Figma frame built from it instead.

Connect design input in Claude Code, Codex, and Cursor

Section titled “Connect design input in Claude Code, Codex, and Cursor”

All three tools read image files, and all three can use the official Figma MCP server and Playwright MCP. The install commands differ; the loop below is the same.

Terminal window
# Figma: the plugin bundles the remote MCP server and Figma's skills
claude plugin install figma@claude-plugins-official
# or the server alone, then run /mcp in a session to log in
claude mcp add --transport http figma https://mcp.figma.com/mcp
# Playwright, so the agent can open and screenshot the prototype
claude mcp add playwright -- npx @playwright/mcp@latest --isolated

Reference exported frames by path in the prompt (design/settings/refs/current.png); Claude Code reads image files directly. Version 2.1.283 also bundles a /design skill, marked research preview in the skills documentation. Treat whatever it produces as a mock to accept, not as the acceptance record. The --chrome flag enables the Claude in Chrome integration for exploring a running app.

The loop produces one folder per feature. Everything the approver and the implementing agent need lives there:

design/settings/
refs/ # current screen, competitor references, brand examples
directions/ # two or three direction mocks, rejected ones kept
prototype.html # the inspectable mock
accepted/ # frames captured from the accepted prototype, per breakpoint and state
acceptance.md # the signed record
  1. Add the visual section to intent.md. Before the agent draws anything, write three facts it cannot guess: the one task the screen must make obvious, the states that exist (empty, loading, error, success, permission denied, destructive confirmation), and the breakpoints that matter. If you cannot name the states, the mock will only show the happy path.

  2. Ask for materially different directions. Directions should differ in hierarchy, density, or navigation, not in colour. The agent writes no production code in this step.

    The owner picks one. Record the choice and one line per rejected direction; the reasons stop the same idea from returning during implementation.

  3. Build the inspectable prototype. Turn the chosen direction into prototype.html, a single file that loads your real token stylesheet and shows every state behind a switch. It is inspectable because anyone can open it in a browser, resize it, and tab through it.

    The prompt serves the prototype over HTTP because Playwright MCP blocks file:// navigation and limits file access to the workspace roots by default (checked on @playwright/mcp 0.0.83). Serving from the repository root lets the prototype load /src/styles/tokens.css exactly as the app does, and the same URL is used for the signed frames in step 4.

  4. Capture the frames the approver signs. Screenshot each state at each breakpoint into accepted/. Run this in a terminal from the repository root, against the same server as step 3; npx playwright screenshot ships with Playwright (checked on 1.63.0). Install the browser once with npx playwright install chromium:

    Terminal window
    python3 -m http.server 8123 & # skip if the step 3 server is still running
    for state in ready empty loading error permission-denied confirm-delete; do
    for vp in "375,812" "1280,800"; do
    npx playwright screenshot --full-page --viewport-size="$vp" \
    "http://localhost:8123/design/settings/prototype.html?state=$state" \
    "design/settings/accepted/$state-${vp%%,*}.png"
    done
    done

    Twelve images are faster to review than one live prototype, and they are the fixed reference the implementation is compared with later.

  5. Iterate, then sign acceptance.md. The owner reviews the frames and the prototype, not a chat transcript. Feedback goes back to the agent as numbered changes; the agent regenerates the frames. When the owner accepts, record it:

    # Visual acceptance: settings screen
    Intent: intent.md#settings (commit a1b2c3d)
    Accepted artifact: design/settings/prototype.html (commit e4f5a6b)
    Frames: design/settings/accepted/*.png (6 states x 2 breakpoints)
    Figma: none (or a version-pinned frame link)
    ## Acceptance criteria
    1. The primary action "Save changes" is the only filled button in every state.
    2. empty: explains how to add the first member and offers one action.
    3. error: keeps the user's input and names the failed field.
    4. permission-denied: shows who can grant access; no disabled form.
    5. confirm-delete: names the workspace and needs the typed name.
    6. 375px: no horizontal scroll; the primary action stays in view.
    7. Keyboard: every control reachable by Tab in visual order; focus visible.
    8. No serious or critical axe violations.
    Approved by: APPROVER_NAME (product design), 2026-09-26
    Out of scope: dark theme (next iteration)

    APPROVER_NAME is the person who owns the decision, not the agent or the implementing developer. Numbered criteria are the point. Each one becomes a check in the next step or an executable acceptance criterion in spec.md.

  6. Hand the folder to the build. Commit design/settings/ with the feature branch. The implementing agent reads acceptance.md and the accepted/ frames during planning, and the plan names which criteria each test covers.

How do you prove the built screen matches the mock without reading the code?

Section titled “How do you prove the built screen matches the mock without reading the code?”

You check the screen against the accepted frames and the numbered criteria. The component code is judged by gates, not by a human reading it line by line.

Run a comparison in a fresh, read-only context. The session that built the screen is the worst judge of it. A separate reviewer opens the running app at each state and breakpoint, compares it with accepted/, and reports only mismatches it can show.

Save the prompt as design/settings/review-prompt.md. Start the app with its fixtures in another terminal first (for example npm run dev); the reviewer has no shell and cannot start it. Then run the review without write access:

Terminal window
claude -p --permission-mode dontAsk \
--allowedTools "Read Grep Glob mcp__playwright" \
< design/settings/review-prompt.md

dontAsk denies every tool call that would prompt and is not in --allowedTools, so the reviewer can read files and drive the browser but cannot edit them. The prompt arrives on stdin because --allowedTools takes a variadic list: a prompt placed after it is read as one more tool name, and claude -p exits with “Input must be provided”.

Lock the result with screenshot baselines. Turn each state into a Playwright test with toHaveScreenshot() and an axe scan; the four-artifact pipeline has a complete spec pattern. The first run creates the baselines. The approver compares them once with accepted/, side by side, and from then on any visual change fails CI until a human approves it.

Who signs what:

CheckProvesSigned by
acceptance.mdThe mock answers the intent, in every state and breakpointProduct or design owner
Fresh-context review reportThe built screen matches the accepted frames, criterion by criterionApprover accepts or rejects each finding
Screenshot baselinesNothing changes visually without approval after mergeDesign (via CODEOWNERS on the snapshot directory)
axe scan and focus assertionsCriteria 7 and 8 holdCode owner

Put the snapshot directory under a CODEOWNERS entry owned by design, and treat an agent-run npx playwright test --update-snapshots as a failed task. The general rule is on protecting the oracle from the agent. Attach the review report and the passing run to the pull request’s evidence bundle.

Only the happy path was mocked. The owner approved a beautiful ready state; the error state ships blank. Recover by listing the states in intent.md first, regenerating the prototype with the state switcher, and refusing to sign acceptance.md while any accepted/ frame is missing.

The mock uses components you do not have. The generated direction shows a segmented control and a colour that exist nowhere in the design system, and the implementation invents both. Recover by adding “reuse only src/components/ui/, flag anything new” to the direction prompt, and grep the prototype for raw colours (rg -n ':\s*#[0-9a-fA-F]{3,8}\b' design/settings/prototype.html matches a property value that starts with a hex colour and must print nothing).

The accepted version lives only in chat. The owner said “option B, but tighter” in a thread, and the next session cannot see it. Recover by treating anything not in acceptance.md as not accepted. Summarise the thread into numbered changes, regenerate the frames, and sign the file.

The approver compares by eye. A review of “looks close enough” misses a missing field label at 375px. Recover by making every criterion in acceptance.md checkable, and letting the fresh-context review report mismatches per criterion instead of giving an overall impression.

The agent that built the screen reviews it. It reports “matches the design” because it remembers its intent, not because it looked. Recover by running the comparison prompt in a new read-only session and requiring a screenshot path for every finding.

The prototype drifts into production code. The fixture route grows real data calls and becomes the feature. Recover by keeping prototypes in design/ or behind a /prototype/ route that the build excludes, and by starting implementation from acceptance.md, not by editing the prototype.

  • intent.md names the task, the states, and the breakpoints.
  • accepted/ holds a frame for every state at every breakpoint.
  • acceptance.md has numbered criteria, a commit reference, an approver, and a date.
  • The fresh-context review report has no open blockers.
  • Screenshot baselines were approved against accepted/ by a human, not generated and accepted by the agent.
  • Design tools and image models stayed inside the approved data boundary.

Back to the developer scorecard answer key.

Frequently asked questions

What is visual acceptance before frontend implementation?

Visual acceptance is a gate between intent.md and frontend code where an agent produces an inspectable UI mock, a named product or design owner signs a versioned acceptance.md, and the implemented screen is checked against those frames before merge.

What media can represent an inspectable UI mock for Scorecard Q7?

Depending on the design risk you need to retire, the inspectable mock can be a Figma frame, a repository HTML prototype, a generated image, or a fixture route covering required states and breakpoints.