Skip to main content

Catch Visual Regressions Before Every PR

A repo skill that makes Devin screenshot every affected page and flag layout breakage before opening a PR.
AuthorCognition
CategoryFeature Development
FeaturesSkills
1

The problem: CSS bugs slip past unit tests

Your test suite passes, CI is green, and the PR gets merged — but the settings page now has overlapping text on mobile, and the checkout button disappeared behind a footer. Unit tests and linters don’t catch visual breakage, so it ships to production and a customer reports it.A repository skill solves this. Skills are markdown files you commit to .agents/skills/<your-skill>/ in any of your repos. Devin sees all skills across all connected repositories — you can trigger them manually or Devin can choose to trigger them automatically when it detects a relevant situation. This skill tells Devin exactly how to boot your app, navigate the pages affected by the diff, and screenshot them at multiple viewport widths — every time, before every PR.
2

Add the visual-regression skill to your repo

Commit a file at .agents/skills/visual-regression/visual-regression.md that encodes your team’s manual QA checklist as steps Devin can follow:
# Visual Regression Check

## Description
Before opening any PR, start the app locally and screenshot every
page affected by the current diff at desktop and mobile widths.
Flag any layout issues found.

## Prerequisites
- Docker running (for the database)
- Port 3000 available

## Setup
1. Install dependencies: `npm install`
2. Start services: `docker-compose up -d postgres redis`
3. Run migrations: `npx prisma migrate dev`
4. Seed test data: `npm run db:seed`
5. Start the dev server: `npm run dev`
6. Wait for "Ready on http://localhost:3000" in the terminal

## Visual Checks
1. Read the current git diff to identify which pages are affected
2. For each affected page:
   a. Open the page in the browser at http://localhost:3000/{route}
   b. Screenshot at 1280px width (desktop)
   c. Resize the browser to 375px width (mobile)
   d. Screenshot at mobile width
   e. Check for: overlapping text, elements hidden behind other
      elements, horizontal scroll, buttons or links that are
      unreachable, missing images or icons, console errors
3. If any issue is found, list it with the page URL, viewport
   width, and a description of the problem

## Before Opening the PR
1. Run `npm run lint` and fix any issues
2. Run `npm test` and confirm all tests pass
3. Include all screenshots in the PR description
4. If issues were found, list them at the top of the PR body
This file ships with your code. Once committed, Devin sees it as an available skill — whenever a session touches UI files in this repo, Devin can trigger the visual regression checks automatically, or you can invoke them manually at any point.
3

Make the checks specific to your pages

Generic instructions like “check the page looks right” produce vague results. The highest-value part of this skill is telling Devin what correct looks like for each area of your app.Add route-specific sections to your skill:
## Route-Specific Checks

### Dashboard (`/dashboard`)
- The metric cards should display in a 3-column grid on desktop
- Cards should stack to a single column on mobile
- The chart should be fully visible without horizontal scroll

### Checkout (`/checkout`)
- The "Place Order" button must be visible without scrolling
  on both desktop and mobile
- The order summary sidebar should collapse into an accordion on mobile
- The price breakdown should show subtotal, tax, and total on separate lines

### Settings (`/settings`)
- All form labels should be left-aligned with their inputs
- The "Save" button must be reachable at the bottom of the form
- Tab navigation between sections should update the URL hash
Devin reads the diff, identifies which routes were touched, and follows the matching section — so checks are focused rather than generic.
4

See it catch a real regression

Suppose an engineer changes the CSS grid on the dashboard from grid-template-columns: repeat(3, 1fr) to repeat(auto-fit, minmax(200px, 1fr)) to make the layout responsive. The unit tests pass — no logic changed. But on mobile, the cards now overflow the viewport.When Devin finishes the code change, it follows the skill automatically:
  1. Boots the app — installs dependencies, starts Docker, runs migrations, seeds data, starts the dev server
  2. Reads the diff — sees that src/components/Dashboard.tsx changed, maps it to the /dashboard route
  3. Screenshots at 1280px — the 3-column grid renders correctly
  4. Screenshots at 375px — spots horizontal overflow: the cards don’t fit in the viewport
  5. Flags the issue — reports “Horizontal scroll detected on /dashboard at 375px width — metric cards overflow the viewport”
  6. Fixes the CSS — adds overflow-x: hidden and adjusts the minmax minimum to 150px
  7. Re-screenshots — confirms the fix at both widths
  8. Opens the PR — includes before/after screenshots and the fix in the description
You can watch this happen in real time via the browser tab in your session workspace.
5

Extend for your stack

Adapt the skill for additional tools and verification steps specific to your project: