# Frontend Mockup Loop

> Plan, build, and iterate UX-friendly frontend mockups via a ground→contract→mockup→test→fix→learn loop, acting as an expert UX designer who grounds every decision in externally documented public design rules (Nielsen heuristics, Laws of UX, WCAG, GOV.UK/USWDS/Material). Uses the bundled serve_mockup, score_mockup, and init_ui_contract tools plus a ui-contract.md design control plane to keep screens consistent. Works in any React/Tailwind/shadcn (or plain HTML) project. Use when designing new screens, adapting existing UI, enforcing cross-screen consistency, or doing a UX review. Triggers: "design a screen", "mockup this UI", "wireframe", "make the UI consistent", "adapt the existing design", "improve this layout", "UX review", "is this good UX".

- Skill: `blackbelttechnology/frontend-mockup-loop` (Agent Skill)
- Install (CLI): `npx skillmds@latest add blackbelttechnology/frontend-mockup-loop`
- Raw SKILL.md: https://api.skillmd.com/api/skills/blackbelttechnology/frontend-mockup-loop/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- License: MIT
- Author: BlackBeltTechnology (https://skillmd.com/u/blackbelttechnology)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/blackbelttechnology/frontend-mockup-loop

---


# frontend-mockup-loop

A disciplined loop for designing frontend surfaces. It exists to defeat
**distributional convergence**: an undirected agent regresses to the
statistical mean of its training data — generic Inter font, a purple gradient,
a centered hero. "Make it look better" just returns the average again.

The fix the whole agentic-design field converged on, and what this loop
enforces every time:

1. **deliberate direction** from a real reference (GROUND),
2. a **consistent token system** (the ui-contract),
3. a **screenshot feedback loop** (eyes on output).

This skill is paired with an extension that registers five tools:
`serve_mockup`, `score_mockup`, `init_ui_contract`, `list_design_systems`,
`validate_mockup`.

## Select a design system (optional)

The loop runs design-system **agnostic** by default (generic anti-slop rubric).
To target a specific system, pick a preset and pass its id to the tools'
`system` param. v1 presets (`list_design_systems` enumerates them):

| id | system | platform | substrate |
|---|---|---|---|
| `shadcn` | shadcn/ui + Tailwind | web | HTML + Tailwind |
| `mui` | Material UI | web | HTML |
| `material-3` | Material Design 3 | web | HTML |
| `fluent-2` | Fluent 2 | web | HTML |
| `apple-hig` | Apple HIG | iOS | HTML approximation → SwiftUI on promote |

With a system selected: `init_ui_contract{system}` writes that system's DTCG
token contract (from a bundled, offline snapshot; `refresh:true` re-fetches
upstream), `score_mockup{system}` swaps in the system's boolean rubric, and
`validate_mockup{system,dir}` runs the gated pipeline.

### Gate vs advisory

Validation is layered. **Gates** block `pass`; **advisory** layers only score
and drive the fix loop (LLM visual scores skew positive — never hard-block):

- **L1 token-lint** — static; HARD GATE when a linter applies (off-token color
  literals fail shadcn/material-3).
- **L2 a11y floor** — rendered axe + WCAG contrast; HARD GATE, every system.
- **L3 named-system auditor** — `hig-doctor` / `material3-mcp` etc., advisory,
  shelled out only if installed (absent → skipped + noted, never errors).
- **L4 vision rubric** — per-preset boolean checks; `score = pass/N` computed in
  code, advisory.

`validate_mockup` returns `{ gates, advisory, pass }`; `pass` is gate-only.

### Apple HIG in a browser-first loop

Apple publishes no token JSON, so `apple-hig` ships a hand-authored rule pack
(`presets-data/apple-hig/rules.md`). Render an **HTML approximation** of the iOS
screen so `serve_mockup` can serve it and `hig-doctor` (if installed) can audit
it — no SwiftUI/Xcode required in-loop:

- SF Pro stack: `font-family: -apple-system, "SF Pro Text", system-ui`.
- 44×44pt minimum tap targets; 8pt spacing grid.
- Safe areas: `padding: env(safe-area-inset-top) … env(safe-area-inset-bottom)`.
- Bottom tab bar, **≤5 items**; iOS semantic colors (label, systemBackground,
  systemBlue), no hardcoded brand hex on system chrome.

On **PROMOTE**, optionally emit real SwiftUI — validated on source by
`hig-doctor` / `orchard-hig` (no live browser preview; real-device fidelity
needs macOS/Xcode). SwiftUI is never required for the in-loop preview.

## Act as an expert UX designer

**Rule: ground every UX decision in an externally documented, public-facing
design rule — never invent one.** When you make a call, you must be able to name
the rule and cite its public source. "I think it looks better" is not a reason;
"Hick's Law — reduce the choices here (lawsofux.com/hicks-law)" is.

The full citable rule corpus lives in
[`references/ux-best-practices.md`](../../../references/ux-best-practices.md):
Nielsen's 10 heuristics, Laws of UX, Gestalt, cognitive load, per-component
pattern rules, the 5-step expert evaluation protocol, and a 22-item checkable
rubric seed. **Read it before designing or reviewing.**

**Source order (adapt, don't copy):** the selected design system's documented
guidance first → then the universal sources, in licensing-safe order (USWDS is
CC0; GOV.UK is OGL; NN/g + Laws of UX cite-with-attribution; Material/Carbon are
Apache-2.0). Adapt the *principle* to this product; never copy proprietary
assets/text (Apple HIG, Refactoring UI, Mobbin).

**Anti-slop companion (advisory).** For the *AI-tell* layer — the countable
signatures an undirected model defaults to (AI-purple, Inter-everywhere,
em-dashes, div-based fake screenshots, eyebrow-per-section, Jane Doe / Acme
data) — pull the `anti-slop-frontend` skill
(`@blackbelt-technology/anti-slop-frontend`). It is **advisory only**: its tells
feed the FIX step's defect list (step 5), but they NEVER override this loop's
hard gates. When an anti-slop tell conflicts with a cited public rule or the
WCAG-AA / severity-4 floor, the cited rule and the gate win. Apply its Part A
(universal) to any surface; skip its Part B (marketing-only) for product UI.

## When to Use

Designing or refining any frontend surface — new screens, redesigns, or a
consistency pass across existing screens. Skip for trivial one-class tweaks.
Not for backend/protocol work.

## Procedure

### 1. GROUND — adapt what ships + what's documented, don't invent
Two grounds, both external:
- **The real UI** — open the running app and READ the authoritative component
  source. Capture the EXACT tokens already in use: class names, CSS custom
  properties (`--background`, `--primary`, `--radius`), spacing, dark + light.
- **The documented rules** — open `references/ux-best-practices.md` and the
  selected design system's public guidance. Identify the specific patterns and
  laws that govern this surface (e.g. a form → NN/g web-form-design + GOV.UK
  error-summary; a nav → Hick's Law + hamburger-menu guidance).

Designing without either ground produces a parallel style that looks "off" and a
UX that violates well-known rules — the opposite of adapting documented design.

### 2. CONTRACT — the consistency control plane
Read or scaffold `ui-contract.md` (run `init_ui_contract`). It is the single
source of truth for cross-screen properties: color ramps, spacing scale, type
scale, radius, elevation, motion, component invariants. **Every value
references a design token — never a raw hex or px literal.** If a surface needs
a token that doesn't exist, add it to the theme layer first, then cite it in
the contract. This file is what stops screens from drifting apart.

### 3. MOCKUP — diverge in HTML, serve it live
Build standalone HTML/Tailwind mockups grounded in steps 1–2. Serve them with
`serve_mockup` and hand back the clickable **local + LAN URL** (the LAN URL
opens on a phone) — **not a screenshot** — so the human reacts to a real page.
Render dark AND light.

### 4. TEST — run the expert-UX evaluation protocol
Run `score_mockup` to capture full-page screenshots at mobile/tablet/desktop
widths, then apply the **5-step protocol** from `references/ux-best-practices.md`:
1. **Accessibility floor (hard gate)** — contrast 4.5:1, target size, focus
   visible, color-not-sole-channel, reduced-motion.
2. **Heuristic boolean rubric** — the 22-item rubric seed (Nielsen + Laws of UX
   + component rules) scored yes/no; for a user flow, the cognitive-walkthrough
   4 questions per step.
3. **PURE friction** — rate each task step green/yellow/red; worst step wins.
4. **Severity 0–4** per defect (Nielsen scale).
5. **Prioritized fix list** — accessibility-gate first, then severity.

**Score = passed / N, derived in code** — never a subjective "looks good" and
never a free-form float (LLM visual scores skew positive). Each failed check
cites the rule it violates.

### 5. FIX — one criterion at a time
Apply the top failing item, re-serve, re-score. Loop 3–5 until every rubric
line passes in both themes at all three breakpoints.

### 6. PROMOTE — close the apply-gap
Translate the approved HTML direction into real React/shadcn components.
Do this in an ISOLATED environment (temp workspace, non-production ports),
never against a live server. Map the mockup's tokens 1:1 so shipped code
matches the approved mockup with zero drift.

### 7. LEARN — compound across runs
Record durable taste decisions so the next run starts smarter: stable rules →
agent memory; repo design rules → patch `ui-contract.md`; one-off rationale →
the change's notes.

## Tools (bundled by the extension)

- `serve_mockup{dir, port?, stop?}` — Node static server on 0.0.0.0; returns
  local + LAN URLs. Zero external deps.
- `score_mockup{url, widths?, outDir?, system?}` — Playwright breakpoint screenshots +
  scoring rubric. Chromium is declared in this package's `pi.tools` (optional
  `pw-browser` probe); absent → install guidance via the registry's Install
  dropdown or `pi-dashboard-ensure` (`npx playwright@1.62.1 install chromium`).
- `init_ui_contract{path?, force?, system?, refresh?}` — scaffold the
  token-referencing contract. With `system`, write that preset's DTCG contract
  (offline snapshot; `refresh` re-fetches upstream first). No `system` →
  generic blank template (unchanged).
- `list_design_systems{}` — enumerate the preset registry (id, label, platform,
  substrate, validators).
- `validate_mockup{system, url?, dir?}` — run L1+L2 (gates) + L3+L4 (advisory);
  returns `{ gates, advisory, pass }`. Pass `dir` so L1/L2 can scan the source.

## Pitfalls

- Do NOT verify against a live/production server — isolate the env so mockup
  edits actually load.
- Do NOT put raw hex/px in the contract or mockups; reference tokens, else
  consistency erodes the moment a theme changes.
- Do NOT skip GROUND — parallel styling looks "off" next to shipped screens.
- Do NOT hand back screenshots for HUMAN review when a live URL is possible.
  Screenshots are for the AGENT's scoring step; live URLs are for the human.
- Do NOT let "make it nicer" be the instruction to yourself — score against the
  named rubric.
- Do NOT invent a UX rule or justify a decision by taste alone — cite an
  external documented public source (see `references/ux-best-practices.md`).
- Do NOT block "pass" on advisory taste while a WCAG-AA or severity-4 defect
  remains — the accessibility floor is the hard gate.

## Verification

- `ui-contract.md` exists; every value references a token; the new surface's
  tokens appear in it.
- A live mockup URL (local + LAN) was handed back and renders in BOTH themes at
  mobile/tablet/desktop.
- A written rubric passes — not a subjective "looks good".
- Every UX decision traces to a cited external rule (heuristic / law / pattern /
  WCAG criterion), not taste.
- The accessibility floor passes (no WCAG-AA or severity-4 defect open).
- If promoted: components were verified in an isolated env; production was left
  untouched.
- Durable learnings were recorded so the loop compounds.

