Coding

Visual Qa

Try it

Perform pixel-level visual regression testing on web apps by capturing, comparing screenshots, and gating deployments based on configurable similarity thresh...

What it does

A visual regression testing pipeline for web applications. Capture baseline screenshots of your app, compare new screenshots against baselines using pixel-level diffing, and pass/fail based on configurable similarity thresholds.

The skill document

Visual QA

A visual regression testing pipeline for web applications. Capture baseline screenshots of your app, compare new screenshots against baselines using pixel-level diffing, and pass/fail based on configurable similarity thresholds.

When to Use

  • Pre-deploy visual verification — gate merges/deploys until UI changes are approved
  • Regression testing — catch unintended visual changes in CI
  • UI review workflow — generate diff images for design/code review
  • Cross-browser/viewport testing — verify responsive layouts
  • Component library QA — ensure design system changes don't break consumers

Quick Start

1. Capture Baselines

# Capture single URL
python scripts/capture.py http://localhost:3000 --output .visual-qa/baselines

# Capture multiple viewports
python scripts/capture.py http://localhost:3000 --viewports desktop mobile tablet --output .visual-qa/baselines

# Capture multiple pages from config
python scripts/capture.py --config .visual-qa.json --output .visual-qa/baselines

2. Compare Against Baselines

# Compare new screenshots
python scripts/diff.py --baseline .visual-qa/baselines --current .visual-qa/current --threshold 99

3. All-in-One Gate

# Capture + diff in one command
python scripts/gate.py --baseline .visual-qa/baselines --url http://localhost:3000 --threshold 99

# With local dev server
python scripts/gate.py --baseline .visual-qa/baselines --server "npm run dev" --port 3000 --threshold 99

# Using config file
python scripts/gate.py --config .visual-qa.json

Config File Pattern

Create .visual-qa.json in your project root:

{
  "urls": ["/", "/about", "/pricing"],
  "baseUrl": "http://localhost:3000",
  "viewports": ["desktop", "mobile"],
  "threshold": 99,
  "server": "npm run dev",
  "port": 3000,
  "baselineDir": ".visual-qa/baselines",
  "ignore": [".visual-qa/diffs", ".visual-qa/current"]
}

Scripts

All scripts support --help for detailed usage.

capture.py

Capture screenshots using Playwright (headless Chromium).

Features:

  • Multiple viewport sizes: desktop (1280x800), tablet (768x1024), mobile (375x812)
  • Waits for networkidle before capture
  • Optional local server start/stop
  • Configurable output directory
  • Descriptive filenames: {url-slug}_{viewport}.png

Usage:

python scripts/capture.py  --output  [options]
python scripts/capture.py --config  --output 

diff.py

Compare screenshots using pixel-level diffing (Pillow).

Features:

  • Pixel-by-pixel comparison
  • Diff images with red/magenta overlay highlighting changes
  • Similarity percentage per image pair
  • Pass/fail based on threshold (default 99%)
  • Summary report with pass/fail status
  • Saves diff images to output directory

Usage:

python scripts/diff.py --baseline  --current  --output  --threshold 

gate.py

All-in-one gate: capture + diff in a single command.

Features:

  • Combines capture and diff steps
  • Starts/stops local server automatically if needed
  • Returns exit code 0 (pass) or 1 (fail)
  • Human-readable summary output
  • Can use config file or CLI args

Usage:

python scripts/gate.py --baseline  --url  --threshold 
python scripts/gate.py --baseline  --server  --port  --threshold 
python scripts/gate.py --config 

Workflow Examples

Initial Baseline Capture

# Start your app
npm run dev

# Capture baselines (desktop + mobile)
python scripts/capture.py http://localhost:3000 --viewports desktop mobile --output .visual-qa/baselines

CI/CD Integration

# In your CI pipeline after build
python scripts/gate.py --baseline .visual-qa/baselines --server "npm start" --port 3000 --threshold 99

# Exit code 0 = pass, 1 = fail
if [ $? -eq 0 ]; then
  echo "Visual QA passed ✓"
else
  echo "Visual QA failed ✗"
  exit 1
fi

Review Workflow

# 1. Developer makes UI changes
# 2. Capture new screenshots
python scripts/capture.py http://localhost:3000 --output .visual-qa/current

# 3. Generate diff images
python scripts/diff.py --baseline .visual-qa/baselines --current .visual-qa/current --output .visual-qa/diffs

# 4. Review diff images in .visual-qa/diffs/
# 5. If changes are intentional, update baselines:
rm -rf .visual-qa/baselines
mv .visual-qa/current .visual-qa/baselines

Multi-Page Testing

Create .visual-qa.json:

{
  "urls": ["/", "/products", "/about", "/contact"],
  "baseUrl": "http://localhost:3000",
  "viewports": ["desktop", "mobile"],
  "threshold": 99,
  "baselineDir": ".visual-qa/baselines"
}
# Capture all pages
python scripts/capture.py --config .visual-qa.json --output .visual-qa/baselines

# Gate all pages
python scripts/gate.py --config .visual-qa.json

Dependencies

Scripts require Playwright and Pillow:

pip install playwright pillow
python -m playwright install chromium

Scripts will check for dependencies and print install instructions if missing.

Thresholds

The --threshold parameter controls similarity percentage (0-100):

  • 99% (default) — strict, catches most visual changes
  • 95% — moderate, allows minor rendering differences (anti-aliasing, fonts)
  • 90% — loose, allows more variation (use for dynamic content)

Experiment to find the right threshold for your app. Start strict (99%) and loosen if you get false positives.

Ignoring Dynamic Content

For pages with dynamic content (dates, user-specific data):

  1. Use data attributes to hide dynamic elements during testing:

    [data-test-hide] { visibility: hidden !important; }
    
  2. Capture specific viewport regions (future enhancement)

  3. Loosen threshold for pages with acceptable dynamic content

Troubleshooting

"Command not found: python"

  • Use python3 instead of python

"Playwright not installed"

  • Run: pip install playwright && python -m playwright install chromium

"Similarity below threshold but images look the same"

  • Font rendering, anti-aliasing, or sub-pixel differences. Lower threshold to 98-95%.

"Server not starting"

  • Check that --port matches your server's port
  • Ensure server command is correct (npm run dev, npm start, etc.)
  • Increase wait time in gate.py (default 5s)

"Images not found"

  • Check that baseline directory exists and contains PNGs
  • Ensure current screenshots were captured to the correct directory
  • Verify filenames match pattern: {url-slug}_{viewport}.png

Tips

  • Commit baselines to Git so your team shares the same reference
  • Add .visual-qa/diffs and .visual-qa/current to .gitignore
  • Run in CI as a required check before merge
  • Update baselines when intentional UI changes are made
  • Use multiple viewports to catch responsive layout issues
  • Test empty/error/loading states by capturing those URLs explicitly

Integration with Other Skills

  • ux-qa-gate — Use visual-qa as part of the UX QA checklist
  • webapp-testing — Combine with Playwright functional tests
  • coding-agent — Sub-agents building UI must pass visual-qa before completion

For detailed script options, run:

python scripts/capture.py --help
python scripts/diff.py --help
python scripts/gate.py --help

Related skills

Join a video meeting as an AI bot with voice, avatar, and screenshare across four operating modes.

by johnpatternai21 installs8 stars

Generate and edit Draw.io, Mermaid, and Excalidraw diagrams from natural language using a structured JSON spec.

by nssa.io1.0k installs47 stars

Stores durable facts in a categorized, plain-markdown vault on disk, alongside your agent's built-in memory.

by Iván1 installs

Fetch raw ad creative, app, ranking, and revenue data from AdMapix as structured JSON.

by fly0pants

More from kbo4sho

Browse all skills

Discover and resolve open source GitHub issues across community repos during idle time. Finds good-first-issue/help-wanted/documentation issues, forks repos,...

by kbo4sho32 installs

Pre-publish audience reaction check. Run any content (tweet, launch copy, pricing page, announcement, blog post) through diverse AI personas before publishin...

by kbo4sho16 installs