Set up automated route-level visual regression testing for web applications (Next.js, Remix, Vite, Astro, Nuxt) in your GitHub Actions CI/CD pipeline in under 5 minutes.
Diffra tests your production build or preview server directly inside GitHub Actions on every pull request:
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Developer opens │ ────► │ GitHub Action │ ────► │ Diff against │
│ Pull Request │ │ builds app routes│ │ Cloud Baselines │
└─────────────────┘ └─────────────────┘ └────────┬────────┘
│
┌─────────────────┐ ┌─────────────────┐ │
│ PR merged into │ ◄──── │ Developer views │ ◄──────────────┘
│ main: Baselines │ │ review link on │ PR Comment & Check
│ auto-promoted │ │ Pull Request │ posted automatically
└─────────────────┘ └─────────────────┘
Install Diffra in your web application repository:
pnpm add -D @diffra/cli @diffra/core @diffra/engineCreate a diffra.config.ts in your project root:
import { defineConfig } from '@diffra/core/config';
export default defineConfig({
// Domain 1: Driver & Routes
drivers: {
driver: 'url',
baseUrl: 'http://localhost:4173',
urls: [
'/',
'/pricing',
{
url: '/dashboard',
name: 'Analytics Dashboard',
group: 'App Routes',
snapshot: {
selector: '#main-content', // Optional selector isolation
delay: 200, // Extra wait time for client-side rendering
mask: ['.user-timestamp'], // Mask dynamic timestamps
},
},
],
},
// Domain 2: Viewport and capture rules
snapshot: {
viewports: [
{ name: 'mobile', width: 375, height: 667 },
{ name: 'desktop', width: 1280, height: 800 },
],
},
});Create .github/workflows/visual-regression.yml:
name: Web App Visual Regression
on:
pull_request:
branches: [main]
push:
branches: [main]
jobs:
visual-regression:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0 # Full history needed for Git merge-base baseline discovery
- uses: pnpm/action-setup@v6
- uses: actions/setup-node@v7
with:
node-version: 24.x
cache: 'pnpm'
- run: pnpm install --frozen-lockfile
- run: pnpm build
# Start production preview server in background
- name: Start preview server
run: pnpm preview --port 4173 &
env:
PORT: 4173
- name: Wait for preview server
run: npx wait-on http://localhost:4173 --timeout 30000
- name: Run Diffra Action
uses: Diffra/core@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
storybookUrl: 'http://localhost:4173'
autoAcceptChanges: 'main'
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
DIFFRA_STORAGE_BUCKET: 'my-app-baselines'
DIFFRA_STORAGE_REGION: 'us-east-1'- Push your branch to GitHub and open a Pull Request.
- The GitHub Action executes, captures screenshots across all configured routes and viewports, and compares them against
mainbaselines in your cloud storage. - A status check and PR comment are automatically posted with a direct link to the visual review UI (
https://viewer.diffra.dev/?report=...). - Merging the PR into
mainautomatically promotes candidate screenshots to cloud storage as the new baseline.
- Deep dive into route configuration, selectors, and masks in Testing web applications and routes.
- Learn how to eliminate font and animation flakiness in Flakiness and determinism.
- Configure cloud storage providers in Storage adapters.