UX Polish Loop

App Factory's structured quality assurance system for React UIs. Combines a 20-pass iterative polish methodology with Playwright E2E testing.

Overview

The UX Polish Loop combines three components to ensure every UI is production-ready:

Ralph

A 20-pass iterative polish methodology that reviews, scores, and fixes until quality meets the threshold.

Playwright

E2E browser testing that verifies real user interactions work correctly across browsers.

Completion Promise

A verifiable definition of done that confirms all acceptance criteria are met.

The 20-Pass System

Each pass follows a systematic sequence until the UI reaches production quality.

1

Run Checks

Execute lint, typecheck, and E2E tests to identify any issues.

2

Evaluate Results

If failures exist, fix the highest-impact issue. If passing, make one high-leverage polish improvement.

3

Document Progress

Record what was done in ralph/PROGRESS.md

4

Check Completion

Verify if all acceptance criteria in ralph/ACCEPTANCE.md are met.

5

Continue or Complete

Write the completion promise if done, or proceed to the next pass. Loop stops when completed or after 20 passes.

The Completion Promise

The loop stops early only when this exact string is written to ralph/PROGRESS.md:

COMPLETION_PROMISE: All acceptance criteria met. UI is production-ready.

This promise requires:

  • All E2E tests passing
  • All lint/typecheck passing
  • All acceptance criteria verified
  • No CRITICAL or HIGH issues remaining

Which Builders Use This?

Website Builder
Next.js websites
dApp Builder
Next.js dApps
App Builder
Mobile-first; Playwright for web exports only
Agent Builder
HTTP API, no UI
Plugin Builder
CLI/API based

Default Smoke Tests

Every UI project gets these baseline tests automatically.

Home page loads- Title exists, no error states
Main content visible- Main element has content
Navigation works- Can navigate between pages
No console errors- Critical errors fail the test
Responsive design- No horizontal scroll on mobile
Accessibility basics- h1 exists, images have alt, keyboard navigation

Polish Priority Order

When all tests pass, improvements are prioritized in this order:

1
User-facing bugs- Broken interactions, visual glitches
2
Accessibility- Missing alt text, focus states
3
Performance- Slow loads, large bundles
4
Visual polish- Alignment, spacing, animation timing
5
Code quality- Refactoring, types, test coverage

Directory Structure

Generated UI projects include these files for the polish loop.

<project>/
├── ralph/
│   ├── PRD.md              # Product requirements
│   ├── ACCEPTANCE.md       # Acceptance criteria
│   ├── LOOP.md             # Loop execution instructions
│   ├── PROGRESS.md         # Pass-by-pass progress log
│   └── QA_NOTES.md         # Manual QA observations
├── tests/
│   └── e2e/
│       ├── smoke.spec.ts   # Core smoke tests
│       └── [feature].spec.ts
├── playwright.config.ts    # Playwright configuration
└── scripts/
    └── ralph_loop_runner.sh  # Human-in-the-loop runner

Running the Loop

Option 1: Script Runner (Recommended)

cd <project>
npm install
npm run polish:ux

Option 2: With Claude Code

cd <project>
claude
# Say: "Run the UX polish loop following ralph/LOOP.md"

FAQ

Why 20 passes?

20 passes is enough to fix most issues and reach completion, but bounded to prevent infinite loops. If 20 passes aren't enough, manual intervention is needed.

Can I skip the loop?

For production UI: No. The completion promise is required. For prototypes: You can skip, but document why in QA_NOTES.md.

What if E2E tests are flaky?

Use stable selectors (data-testid), add explicit waits (waitForLoadState), and retry on CI only.

Next Steps