Iron Law
DO NOT REPLACE reality-checker — USE IT FIRST for live browser screenshots and binary APPROVED/NEEDS WORK verdict. This skill adds: (1) visual regression tooling setup for CI/CD pipelines, (2) the 13-item mandatory verification checklist for systematic pre-PR checks, (3) automated screenshot diff configuration. Use both together.
UI Visual Validator
Systematic visual verification methodology + CI/CD visual regression tooling. Skeptic-first: the modification goal has NOT been achieved until proven with visual evidence.
Scope vs reality-checker
| Capability | reality-checker agent |
ui-visual-validator (this skill) |
|---|---|---|
| Live browser screenshot | ✅ Chrome DevTools MCP | ❌ (use reality-checker for this) |
| Binary APPROVED/NEEDS WORK verdict | ✅ | ❌ (defer to reality-checker) |
| Visual regression tool setup (CI/CD) | ❌ | ✅ Chromatic, Percy, Applitools, BackstopJS |
| GitHub Actions visual diff workflow | ❌ | ✅ |
| 13-item mandatory verification checklist | ❌ | ✅ |
| Accessibility visual compliance checklist | ❌ | ✅ |
| Pre-commit systematic analysis protocol | ❌ | ✅ |
Workflow: Run ui-visual-validator checklist → gather screenshots → pass to reality-checker for final verdict.
When to Use This Skill
- Setting up Chromatic, Percy, or Playwright Visual in a CI/CD pipeline
- Before a PR that touches Angular components or Flutter screens — run through the 13-item checklist
- Investigating "it looks different on CI than locally" — visual regression diagnosis
- New Angular component needs visual baseline established for regression testing
- Flutter screen needs screenshot test added to CI
When NOT to Use This Skill
- For live browser screenshots — use
browser-testingskill + Chrome DevTools MCP - For the final APPROVED/NEEDS WORK gate — use
reality-checkeragent - For WCAG compliance audit — use
accessibility-auditskill
Core Principle
The modification goal has NOT been achieved until proven by visual evidence. Ignore code hints. Base judgments solely on visual output.
Forbidden behaviors:
- Assuming code changes automatically produce correct visual results
- Quick conclusions without systematic analysis
- Accepting "looks different" as "looks correct"
- Using expectation to replace direct observation
Required output format (when performing visual analysis): Always start with: "From the visual evidence, I observe..."
13-Item Mandatory Verification Checklist
Run through ALL 13 items before declaring a UI change complete:
Structural
- 1. Objective description — Described actual visual content without assumptions?
- 2. Goal verification — Compared each element against stated modification goals systematically?
- 3. Measurement validation — For rotation/position/size changes: verified through actual visual measurement (not assumed from code)?
Visual Quality
- 4. Responsive breakpoints — Verified at 375px, 768px, 1024px, 1440px?
- 5. Dark/light mode — Both themes validated (if applicable)?
- 6. Loading and transition states — Skeleton/spinner shown correctly? Transitions smooth?
- 7. Error and edge cases — Empty states, error states, disabled states all verified?
Accessibility (Visual)
- 8. Color contrast — WCAG 4.5:1 minimum for normal text verified visually?
- 9. Focus indicators — Visible focus rings on interactive elements?
- 10. Touch targets — Interactive elements >= 44px (Angular) / 48dp (Flutter)?
Design System
- 11. Token compliance — No hardcoded colors visible that should use semantic tokens?
- 12. Design system alignment — Component matches design system spec?
Regression
- 13. Reverse validation — Actively looked for evidence the modification FAILED (not just succeeded)?
Visual Regression Tool Setup
Option 1: Playwright Visual (Recommended for Angular)
# Install
npm install -D @playwright/test
# angular.json — add e2e target
// visual.spec.ts
import { test, expect } from '@playwright/test';
test('dashboard visual regression', async ({ page }) => {
await page.goto('/dashboard');
await page.waitForLoadState('networkidle');
// Full page snapshot
await expect(page).toHaveScreenshot('dashboard.png', {
fullPage: true,
threshold: 0.1, // 10% pixel difference tolerance
});
});
test('mobile breakpoint', async ({ page }) => {
await page.setViewportSize({ width: 375, height: 812 });
await page.goto('/dashboard');
await expect(page).toHaveScreenshot('dashboard-mobile.png');
});
# .github/workflows/visual-regression.yml
name: Visual Regression
on: [pull_request]
jobs:
visual-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- run: npx playwright install --with-deps chromium
- run: npx ng build --configuration=production
- run: npx playwright test --reporter=html
- uses: actions/upload-artifact@v4
if: failure()
with:
name: playwright-visual-report
path: playwright-report/
Option 2: Chromatic (Storybook-based, component-level)
npm install --save-dev chromatic
npx chromatic --project-token=<token> --auto-accept-changes main
# GitHub Actions
- name: Publish to Chromatic
uses: chromaui/action@latest
with:
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
onlyChanged: true # Only test changed components
Best for: Angular component libraries with Storybook stories.
Option 3: BackstopJS (Config-based, no Storybook needed)
npm install -g backstopjs
backstop init
// backstop.json
{
"viewports": [
{ "label": "mobile", "width": 375, "height": 812 },
{ "label": "tablet", "width": 768, "height": 1024 },
{ "label": "desktop", "width": 1440, "height": 900 }
],
"scenarios": [
{
"label": "Dashboard",
"url": "http://localhost:4200/dashboard",
"selectors": ["#main-content"],
"delay": 500,
"misMatchThreshold": 0.1
}
],
"engine": "playwright"
}
backstop reference # Create baseline screenshots
backstop test # Compare against baseline
backstop approve # Approve changes as new baseline
Option 4: Percy (Cross-browser, cloud-based)
npm install --save-dev @percy/cli @percy/playwright
// In Playwright test
import percySnapshot from '@percy/playwright';
test('dashboard', async ({ page }) => {
await page.goto('/dashboard');
await percySnapshot(page, 'Dashboard');
});
Flutter Visual Testing
// widget_test.dart — golden file testing
import 'package:flutter_test/flutter_test.dart';
import 'package:golden_toolkit/golden_toolkit.dart';
testGoldens('DashboardScreen renders correctly', (tester) async {
await loadAppFonts();
final builder = DeviceBuilder()
..overrideDevicesForAllScenarios(devices: [
Device.phone,
Device.iphone11,
Device.tabletPortrait,
])
..addScenario(
widget: const DashboardScreen(),
name: 'default state',
)
..addScenario(
widget: const DashboardScreen(isLoading: true),
name: 'loading state',
);
await tester.pumpDeviceBuilder(builder);
await screenMatchesGolden(tester, 'dashboard');
});
# Generate golden files (baseline)
flutter test --update-goldens
# Run comparison
flutter test
Analysis Protocol
When performing visual analysis:
- Describe first — What is literally visible? (shapes, colors, positions, text)
- Verify goals — Does each element match the stated change?
- Measure — For rotation/size/position: measure actual pixels, don't estimate
- Reverse-validate — What would failure look like? Is that what I see?
- Accessibility — Is contrast sufficient? Are focus rings visible?
- Cross-platform — Same breakpoints, same themes?
- Edge cases — Long text, empty states, error states?
- Conclude — "From the visual evidence, I observe [X]. The goal [is/is not] achieved because [Y]."
How This Fits the Review Stack
| Layer | Tool | What It Catches |
|---|---|---|
| Layer 1 — Design tokens | /lint-design-system |
Hardcoded colors, raw spacing |
| Layer 2 — WCAG | accessibility-auditor agent |
Contrast, ARIA, keyboard nav |
| Layer 3 — Interaction patterns | web-design-guidelines |
Loading/empty/error states |
| Layer 4 — Live screenshot | reality-checker agent |
Binary pass/fail with visual evidence |
| Layer 5 — CI regression | ui-visual-validator (this skill) |
Baseline regression, cross-browser |
Related Skills and Agents
reality-checkeragent — run BEFORE this skill for live browser verdict (Chrome DevTools MCP)browser-testingskill — Chrome DevTools MCP + Browser-Use for live UI interactionaccessibility-auditskill — deeper WCAG 2.1 AA compliance (beyond visual checks)web-design-guidelinesskill — Vercel Web Interface Guidelines audit (loading/error/empty state patterns)design-systemskill — token compliance enforcement