SKILL.md
Browser Visual QA
Type checks and unit tests say nothing about whether the interface looks right or works for a person. Meaningful UI work is not done until it has been exercised in a real browser. If the environment cannot render the surface, say so plainly instead of claiming success.
Tooling
Use a browser automation CLI if one is installed (agent-browser, Playwright's CLI, or equivalent). Check with which agent-browser || npx playwright --version. The commands below use agent-browser; map them to your tool if different. Prefer accessibility-tree refs and role/text/label locators over raw CSS selectors: they mirror how users and assistive tech perceive the page, and they break less.
Core QA loop
# 1. Open the surface (dev server running first)
agent-browser open http://localhost:3000
# 2. Perceive: accessibility tree with refs
agent-browser snapshot
# 3. Capture visual truth
agent-browser screenshot ./qa/home.png
# 4. Drive it like a user
agent-browser find role button "Get started" click
agent-browser type "#email" "test@example.com"
agent-browser press Enter
# 5. Read what broke
agent-browser console
agent-browser errorsBatch a scripted flow for one deterministic run:
agent-browser batch --bail \
"open http://localhost:3000" \
"find role link 'Pricing' click" \
"wait 'text=Choose a plan'" \
"screenshot ./qa/pricing.png"Responsive and theme matrix
agent-browser set viewport 375 812 # narrow
agent-browser screenshot ./qa/m.png
agent-browser set viewport 1440 900 # wide
agent-browser set media dark
agent-browser set media light reduced-motionMinimum matrix: narrow (~375px) and wide (~1440px), light and dark, plus reduced motion. This is where generated UI usually breaks: overflow, clipped text, broken grids, invisible focus, contrast loss on dark.
Regression diffing
agent-browser screenshot --baseline ./qa/baseline/home.png # save when happy
agent-browser diff screenshot --baseline # pixel/layout diff
agent-browser diff snapshot # accessibility-tree diffUse both. The screenshot diff catches visual regressions; the snapshot diff catches semantic ones, like a button that lost its name or a heading that disappeared.
Performance signal
agent-browser vitals http://localhost:3000 --jsonReads LCP, CLS, TTFB, FCP, INP. Treat LCP and CLS regressions as blockers on marketing surfaces. A hero animation that tanks LCP is not shippable.
What to look for
- Layout: overflow, clipped or truncated text, misaligned grids, collisions at edge widths
- Hierarchy: everything the same weight and size, no visual priority
- States: empty, loading, error, and long-content states missing or broken
- Interaction: golden path fails, dead buttons, focus invisible on keyboard
- Responsive: desktop layout collapsing on mobile, horizontal scroll
- Console: hydration warnings, 404 assets, uncaught exceptions
- Theme: contrast failures or invisible elements in dark mode
Good vs bad
Bad: "Built the pricing page, tests pass, done." No browser was opened. The CTA overlaps the nav at 375px and the dark theme renders gray-on-gray.
Good: "Golden path clicked through at 375 and 1440, light and dark. Screenshots in ./qa/. Console clean except one 404 for a missing favicon, fixed. LCP 1.9s. Empty state verified with a cleared account."
Verification
Run the golden path end to end in the browser, then run agent-browser console and agent-browser errors. Expect: every step of the flow completes from the UI, and both outputs are empty of uncaught errors and hydration warnings. If the flow breaks, capture the failing screenshot and fix before shipping. If the surface cannot be rendered in this environment, report "not verified: no render environment" instead of a pass.
Completion checklist
- [ ] Golden path exercised end to end in a real browser
- [ ] Screenshots captured at narrow and wide widths, light and dark
- [ ] Console and page errors clean
- [ ] Regression diff run where a baseline exists (screenshot and snapshot)
- [ ] Web Vitals checked, LCP/CLS within budget for the surface
- [ ] Empty, loading, error, and long-text states inspected
- [ ] Any unrenderable surface reported plainly, no false verified
Any box unchecked: not done. Fix or say so.
Footguns
- Happy-state-only QA. The page looks fine with perfect seed data, then production shows an empty list and a broken layout. Fix: force empty, loading, error, and overflow states explicitly before signing off.
- CSS-selector scripts. Flows keyed to
.btn-primary:nth-child(2)break on every refactor and test nothing about usability. Fix: locate by role, text, or label; act by snapshot ref. - Screenshot diff without a controlled viewport. Different viewport or font loading between runs produces noise diffs that get ignored, and then real regressions get ignored too. Fix: pin viewport and wait for load state before every baseline and comparison shot.