Pre-Delivery — The UI Checklist & Playwright Verification
UI work is not done when the code is written — it is done when the checklist passes and Playwright screenshots confirm the build.
The Gap Between "Code Written" and "Done"
There is a persistent myth in AI-assisted frontend development: the work is done when the code compiles. TypeScript passes. The build succeeds. The component renders. Done.
This is wrong. Compilation and rendering tell you that the code is structurally correct. They tell you nothing about whether body text is ≥16px, whether headings are ≥600 weight, whether text colors pass the brightness floor, whether cards use 1px borders, whether hover transitions are 150ms and not 350ms. These are the properties that determine whether the UI is actually correct — and none of them are caught by a compiler or a bundler.
Knox's pre-delivery process runs for every PR that changes frontend components on any of the five ecosystem properties. The checklist is from design-intelligence.md Part 3. The Playwright suite runs against every academy lesson page. The visual retro documents what changed and what was caught.
The Pre-Delivery Checklist
The checklist is organized into five categories because design system violations cluster into five areas: typography, color and contrast, component structure, content, and cross-site rules. Each category has 3-4 checks, for 21 total.
The verification method column is critical. "DevTools → computed font-size on every p/li/span" is not a suggestion — it is the exact tool and the exact property. Guessing is not verification. Running the DevTools check on one paragraph and assuming the rest are correct is not verification. The checklist is comprehensive because AI generates inconsistencies: one paragraph at 14px while the rest are 16px is exactly the kind of violation that slips through visual inspection.
The most commonly violated checks are:
- No font-weight 300 anywhere — AI uses it by default. Grep/search before every PR.
- No slate-500 for body copy — AI uses it for "secondary" text that is not actually secondary.
- Hover transition ≤ 150ms — AI defaults to 200–300ms transitions that feel sluggish.
- Ecosystem backlinks present — Easy to forget when building standalone components.
Playwright as the AI's Eyes
AI cannot see the rendered UI. It generates code, but it has no way to verify what that code produces in a browser unless it runs the browser and reads the output.
Playwright is the mechanism for that. It opens the real browser, renders the component with real CSS, and reads the actual computed styles. This is different from static analysis — it is runtime verification.
The five phases of the Playwright verification flow:
Phase 1 — Setup: Configure base URL, viewports (desktop + mobile), and tag smoke tests with @smoke. The smoke suite runs quickly before every PR.
Phase 2 — Screenshot Pass: page.screenshot({ fullPage: true }) for visual comparison. page.locator('h1').screenshot() for component-level verification. toMatchSnapshot() for baseline comparison — fails CI if a visual regression appears.
Phase 3 — Typography Verification: page.evaluate(() => getComputedStyle(element)) reads the actual computed styles. Assert that font-size is ≥16px, font-weight is ≥400, color is ≥#94A3B8 brightness. These assertions are the automated checklist.
Phase 4 — Interaction Smoke Tests: Hover over cards to verify 150ms transition. Toggle the theme to verify dark/light mode works without invisible text. Set mobile viewport to verify font-size does not shrink below 16px.
Phase 5 — Visual Retro: Generate the HTML report. Store screenshots to docs/screenshots/ (version-controlled with the PR). Log any violations found in RETRO.md.
Write the smallest version of Phases 1-3 yourself: a @smoke test that loads the page, confirms a key element renders, and asserts the typography hard rules from the computed styles.
The Visual Retro Loop
The visual retro closes the learning loop. Without it, violations found during the current build are forgotten by the next session.
The retro template captures: what was found, which MASTER.md rule it violated, the root cause, the fix, and whether the rule was escalated to CLAUDE.md. The escalation step is important: if the same violation appears twice, the rule is not strong enough in the current constraint system. Escalation means adding a more explicit instruction to MASTER.md, to the master prompt template, or to CLAUDE.md itself.
Knox's CLAUDE.md typography hard rules are escalated lessons from previous visual retros. The font-weight 300 ban came from a jeremyknox.ai build where AI used 300 weight on a dark background. The #94A3B8 floor came from an academy component where AI used #64748b for body copy. Each rule in CLAUDE.md was learned from a real violation. The visual retro is the mechanism that surfaces those lessons.
The Build Order
The pre-delivery checklist and Playwright verification fit into the full build order:
- PRD — requirements and acceptance criteria
- UX Audit — reference extraction, MASTER.md generation
- Test Strategy — Playwright spec written before components
- Build — components against MASTER.md constraints
- Playwright Verification — computed style assertions, screenshots
- Pre-Delivery Checklist — all 21 checks against the running app
- Visual Retro — document findings, escalate rules
- PR — everything passes before the PR is created
This is the order that produces frontend work that does not regress after merge. Steps 1-4 are the build. Steps 5-7 are the verification. Step 8 is the delivery. Skipping any step is skipping part of the build.
The pre-delivery checklist and Playwright verification are the final constraint in the design system workflow. The MASTER.md constrains what AI builds. The checklist verifies what was built. Playwright confirms it in the browser. The retro captures what slipped through. Together, they close the loop that the design system opens.
The AI aesthetic trap is solved at the “Why AI Frontends Look Generic” lesson with constraints. This lesson is the verification that the constraints held. Both are necessary. Neither is optional.