agentleFS
mlopscommunitymlopscommunity/Coding-Agents-Conference-skills/skills/visual-regression/SKILL.md

visual-regression

Skill38 starsChanged 8 months agoApache-2.0View on GitHub

Use when making user-facing UI changes and you want automated screenshot walkthroughs, or at release time to compare visual changes between releases and prioritize what needs human review. Requires Playwright.

7 other projects use a version of this.

Adopted by

Most recently taken up by

The file

We split this skill into the rules it gives an agent

10 rules. 0 are common, 6 are distinctive, and 4 are very specific to this project.

  • 0

    Common

    Most of the 7 edited versions we read keep these.

  • 6

    Distinctive

    This author's own choices. Worth a look.

  • 4

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    After making any user-facing change (component, layout, CSS, copy)

    line 18
  2. Distinctive:

    Before a release to catch accumulated visual regressions

    line 19
  3. Distinctive:

    When QA is a bottleneck and you need to prioritize what humans review

    line 20
  4. Distinctive:

    When you make a user-facing change, do this:

    line 39
  5. Distinctive:

    Look at what you changed and list the user flows it touches (e.g., "login flow", "checkout step 2").

    line 43
  6. Very specific:

    Create scripts under e2e/visual/ that walk through each affected flow and capture screenshots at each meaningful step.

    line 47
  7. Very specific:

    Write a manifest at .screenshots/manifest.json describing each flow and screenshot:

    line 75
  8. Very specific:

    Commit: e2e/visual/*.spec.ts and .screenshots/manifest.json

    line 117
  9. Very specific:

    Use pixelmatch or Playwright's built-in comparison.

    line 152
  10. Distinctive:

    Screenshots are dev artifacts, not source code: Never commit them. They can always be regenerated.

    line 222

“Common” is measured: kept by at least 6 in 10 of the 7 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Visual Regression Testing

Overview

Two-mode skill for catching visual regressions. During development, create screenshot walkthroughs of affected flows. At release time, compare screenshots between two git refs and use a sub-agent to classify changes as expected or unexpected.

Core principle: Screenshots are cheap and regenerable. Never commit them to git. The value is in the comparison and classification, not the screenshots themselves.

Dependency: Playwright must be installed in the project.

When to Use

  • After making any user-facing change (component, layout, CSS, copy)
  • Before a release to catch accumulated visual regressions
  • When QA is a bottleneck and you need to prioritize what humans review

When NOT to Use

  • API-only or backend-only changes
  • As a CI gate on PRs (too slow — run at release time only)

Common Mistakes

MistakeWhy it's wrong
Committing screenshots to gitThey're regenerable. Bloats repo for no value.
Running visual comparison in CI on every PRToo slow. Rob: "You cannot do this in PR merge."
Using hard-coded pixel thresholds aloneThe key insight is AI-powered analysis of why something changed, not just that it changed.
Over-engineering with versioned baselines and symlinksKeep it simple: checkout old tag, screenshot, checkout new tag, screenshot, diff.
Skipping the textual walkthroughScreenshots without descriptions are useless for review. Always include what the user sees and what flow this belongs to.

Mode 1: document (During Development)

When you make a user-facing change, do this:

Step 1: Identify affected flows

Look at what you changed and list the user flows it touches (e.g., "login flow", "checkout step 2").

Step 2: Write or update Playwright screenshot scripts

Create scripts under e2e/visual/ that walk through each affected flow and capture screenshots at each meaningful step.

// e2e/visual/login-flow.spec.ts
import { test } from '@playwright/test';

test('login flow walkthrough', async ({ page }) => {
  // Step 1: Landing page
  await page.goto('/');
  await page.waitForLoadState('networkidle');
  await page.screenshot({ path: '.screenshots/flows/login-flow/01-landing-page.png', fullPage: true });

  // Step 2: Click login, see form
  await page.click('[data-testid="login-button"]');
  await page.waitForSelector('[data-testid="login-form"]');
  await page.screenshot({ path: '.screenshots/flows/login-flow/02-login-form.png', fullPage: true });

  // Step 3: Fill and submit
  await page.fill('[name="email"]', 'test@example.com');
  await page.fill('[name="password"]', 'password123');
  await page.click('[data-testid="submit"]');
  await page.waitForSelector('[data-testid="dashboard"]');
  await page.screenshot({ path: '.screenshots/flows/login-flow/03-dashboard.png', fullPage: true });
});

Step 3: Update the manifest

Write a manifest at .screenshots/manifest.json describing each flow and screenshot:

{
  "flows": [
    {
      "name": "login-flow",
      "description": "User logs in from landing page to dashboard",
      "screenshots": [
        {
          "file": "flows/login-flow/01-landing-page.png",
          "description": "Landing page with login button in top nav",
          "step": "Navigate to /"
        },
        {
          "file": "flows/login-flow/02-login-form.png",
          "description": "Login modal with email and password fields",
          "step": "Click login button"
        },
        {
          "file": "flows/login-flow/03-dashboard.png",
          "description": "Dashboard view after successful login",
          "step": "Submit valid credentials"
        }
      ],
      "changed_by": "commit abc1234 - Add social login buttons"
    }
  ]
}

Step 4: Gitignore screenshots, commit scripts and manifest

# .gitignore
.screenshots/flows/
.screenshots/baseline/
.screenshots/current/
.screenshots/diffs/
.screenshots/report.md

Commit: e2e/visual/*.spec.ts and .screenshots/manifest.json

Mode 2: compare (At Release Time)

digraph compare {
  "Checkout old release tag" -> "Run all screenshot scripts" [label="save to .screenshots/baseline/"];
  "Run all screenshot scripts" -> "Checkout new release tag";
  "Checkout new release tag" -> "Run same scripts again" [label="save to .screenshots/current/"];
  "Run same scripts again" -> "Pixel diff each pair";
  "Pixel diff each pair" -> "Any diffs?" [shape=diamond];
  "Any diffs?" -> "Done - no regressions" [label="no"];
  "Any diffs?" -> "Sub-agent analyzes each diff" [label="yes"];
  "Sub-agent analyzes each diff" -> "Generate prioritized report.md";
}

Step 1: Generate baseline screenshots (old release)

git checkout v1.2.0
npx playwright test e2e/visual/ --project=chromium
# Screenshots saved to .screenshots/baseline/
git checkout -  # back to current branch

Step 2: Generate current screenshots (new release)

npx playwright test e2e/visual/ --project=chromium
# Screenshots saved to .screenshots/current/

Step 3: Pixel diff

Use pixelmatch or Playwright's built-in comparison. For each screenshot pair (baseline vs current), generate a diff image if pixels changed.

Step 4: Sub-agent classification (the key innovation)

For every screenshot that differs, spawn a sub-agent with:

Input:

  • The baseline image
  • The current image
  • The diff image
  • The list of merged PRs/commits between the two tags (git log v1.2.0..v1.3.0 --oneline)
  • The manifest entry describing what this screenshot shows

Prompt the sub-agent:

Look at the baseline and current screenshots. Identify what visually changed. Then check the merged PRs between these releases. Classify this change:

  • Expected: A merged PR explicitly intended this visual change
  • Unexpected: No merged PR explains this change — possible regression

Assign a risk level:

  • High: Unexpected change, or change to a payment/auth/data-entry flow
  • Medium: Expected change but large visual impact
  • Low: Expected minor change (copy, spacing, color tweak)

Return: classification, risk level, what changed, which PR caused it (if expected), and recommendation.

Step 5: Generate report

Write .screenshots/report.md:

# Visual Regression Report
**Baseline**: v1.2.0 | **Current**: v1.3.0
**Date**: 2026-03-04
**Screenshots**: 24 total | 8 changed | 16 unchanged

## High Risk
### checkout-flow/03-confirmation.png
- **Classification**: Unexpected
- **What changed**: Payment total lost decimal formatting ($50 instead of $50.00)
- **Related PRs**: None found
- **Recommendation**: Investigate before release

## Medium Risk
### dashboard/01-main-view.png
- **Classification**: Expected
- **What changed**: New sidebar navigation added
- **Related PR**: #187 — Add sidebar nav
- **Recommendation**: Verify sidebar matches design spec

## Low Risk
### login-flow/01-landing-page.png
- **Classification**: Expected
- **What changed**: Updated logo
- **Related PR**: #192 — Brand refresh
- **Recommendation**: No action needed

Quick Reference

ItemLocation
Screenshot scriptse2e/visual/*.spec.ts
Flow manifest.screenshots/manifest.json
Baseline screenshots.screenshots/baseline/ (gitignored)
Current screenshots.screenshots/current/ (gitignored)
Diff images.screenshots/diffs/ (gitignored)
Comparison report.screenshots/report.md (gitignored)

Key Principles

  1. Screenshots are dev artifacts, not source code. Never commit them. They can always be regenerated.
  2. This is NOT a CI tool. It's too slow for PR merge. Run it at release time on a separate build box.
  3. The sub-agent analysis is what makes this valuable. Raw pixel diffs are noise. AI classification against merged PRs turns noise into signal.
  4. Chromium only. Cross-browser pixel comparison is unreliable. Use one browser for deterministic results.
  5. The manifest is the contract. It tells future agents and humans what each screenshot means and what flow it belongs to.

Attribution

Based on Rob's technique from the Coding Agents: AI Driven Dev Conference. Rob uses this across multiple projects and calls it a "massive accelerant" for release QA.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.