How to Set Up Reg-suit Image Comparison for a Static Website
Set up repeatable static-site screenshots, configure Reg-suit baselines and thresholds, and run visual comparisons in CI.
Reg-suit compares image files and produces an HTML visual-difference report; it does not capture your website. To use it with a static site, build the site, generate screenshots under stable browser conditions, point Reg-suit’s core.actualDir at those files, configure how expected snapshots are selected and stored, then run npx reg-suit run after capture in local development or CI. The Reg-suit project describes it as “a command line interface for visual regression testing.” Reg-suit README
1. Plan the capture set
Choose the routes and browser conditions you want to protect before configuring comparison. Each image should represent one page or state, with a stable filename that will be produced on every run.
- Routes: include representative pages and important states, such as a navigation menu opened or a form error state, if those are in scope.
- Viewport: choose explicit width and height values. Add separate captures for mobile and desktop when both matter.
- Browser conditions: keep the browser version, device scale, fonts, locale, timezone, and color scheme consistent between baseline and candidate runs.
- Wait conditions: wait for the page’s meaningful content and fonts to load. Avoid arbitrary long sleeps where a selector or network-idle condition is more reliable.
- Output: write image files into one known directory, such as
screenshot/. Reg-suit uses this directory as its actual-image input.
These are workflow choices, not universal settings: use conditions that match your site’s rendering and test goals. The official Puppeteer demo shows a capture script that writes a screenshot into a directory before Reg-suit runs. Official Puppeteer demo
2. Build the site and capture screenshots
Install a browser capture tool that fits your existing project. The official example uses Puppeteer. The following standalone Node.js example assumes the static site is built into dist/ and will be served locally at http://127.0.0.1:4173. Start a local static server in a separate process before running it, or replace the URL with your existing preview server.
npm install --save-dev puppeteer
mkdir -p scripts screenshot
Create scripts/capture.mjs:
import fs from 'node:fs/promises';
import path from 'node:path';
import puppeteer from 'puppeteer';
const origin = process.env.SITE_ORIGIN ?? 'http://127.0.0.1:4173';
const outDir = path.resolve('screenshot');
const pages = [
{ name: 'home', route: '/' },
{ name: 'about', route: '/about/' },
];
await fs.mkdir(outDir, { recursive: true });
const browser = await puppeteer.launch({ headless: true });
try {
const page = await browser.newPage({
viewport: { width: 1365, height: 900 },
deviceScaleFactor: 1,
});
await page.emulateMediaFeatures([{ name: 'prefers-reduced-motion', value: 'reduce' }]);
for (const item of pages) {
const response = await page.goto(new URL(item.route, origin).href, {
waitUntil: 'networkidle0',
timeout: 30000,
});
if (!response || !response.ok()) {
throw new Error(`Could not load ${item.route}: HTTP ${response?.status() ?? 'no response'}`);
}
await page.evaluate(() => document.fonts.ready);
await page.screenshot({
path: path.join(outDir, `${item.name}.png`),
fullPage: true,
animations: 'disabled',
});
}
} finally {
await browser.close();
}
Adapt the routes, viewport, and readiness condition to your site. If analytics or long-polling prevents networkidle0, wait for a page-specific selector instead. For pages with delayed content, wait for that content explicitly. If you capture full pages, ensure the site lazily loads below-the-fold images as the page is scrolled; otherwise the screenshot may capture placeholders. Keep screenshot names and capture settings identical for the expected and candidate runs.
3. Install and initialize Reg-suit
Install Reg-suit as a development dependency and initialize its project configuration:
npm install --save-dev reg-suit
npx reg-suit init
The initializer is interactive. It can configure the working directory, actual image directory, threshold, a key-generator plugin, and a publisher plugin. Prompt wording and plugin behavior can vary by installed version, so use the current prompts and the plugin’s own README as the authority. Reg-suit’s README lists reg-suit init for setup and reg-suit run as the integrated run command. Reg-suit README
A minimal root-level regconfig.json for the capture example can look like this:
{
"core": {
"workingDir": ".reg",
"actualDir": "screenshot",
"thresholdRate": 0
}
}
Use the key-generator and publisher configuration written by the initializer when you need managed baselines. The sample threshold of 0 is only an example, not a universal recommendation. Reg-suit documents a threshold from 0 to 1; smaller values make comparison more sensitive. Review your own reports before choosing a value. Configuration reference in the README
4. Choose baseline keys and snapshot storage
Reg-suit needs a way to determine which prior images are the expected set for the current comparison. It also needs somewhere to retrieve and, when configured, publish those snapshots and reports.
Git-based keys
The reg-keygen-git-hash-plugin identifies a comparison commit by walking the Git branch graph. This supports a common workflow where a topic branch compares against a snapshot associated with its base history. It depends on usable branch history and a checkout that exposes the relevant branch and commits; shallow or detached checkouts can prevent the plugin from identifying the intended base.
Explicit keys
The Reg-suit README also lists a simple key-generator plugin. Consider an explicit key if your workflow assigns snapshot identities itself or cannot provide the branch history the Git-hash approach needs. Select the plugin based on how your team defines the expected baseline, and verify the installed plugin’s configuration details.
Publishers
The S3 publisher fetches prior snapshots for comparison and publishes current snapshots and the report after a run. It requires a bucket accessible from the environment running Reg-suit. Its documented IAM policy includes s3:DeleteObject, s3:GetObject, s3:GetObjectAcl, s3:PutObject, s3:PutObjectAcl, and s3:ListBucket. Review the plugin documentation and your organization’s current AWS access policy before granting permissions. Options documented by the plugin include bucket name, encryption settings, custom domain, path prefix, and SDK options. S3 publisher README
Reg-suit also lists a GCS publisher. Choose storage based on your existing cloud setup, access controls, and operational requirements; the sources cited here do not establish current storage pricing. Reg-suit README
5. Set comparison behavior
| Setting | What to decide |
|---|---|
core.workingDir |
Where Reg-suit keeps working data, such as .reg. |
core.actualDir |
The directory containing screenshots from the current capture run. It must match the capture output directory. |
core.thresholdRate |
Sensitivity from 0 to 1 in the documented configuration; lower values are more sensitive. Tune from your own reports. |
| Key-generator plugin | How the run identifies the expected snapshot set: Git history or a configured key strategy. |
| Publisher plugin | Where expected snapshots and reports are retrieved and published, such as S3 or GCS. |
The README also lists optional antialias handling, detailed difference reporting through x-img-diff-js, and a concurrency setting. Check the current README and installed version for exact names and accepted values before adding these options. Avoid making a threshold compensate for unstable capture conditions: first make the browser output repeatable, then decide what differences should be accepted.
6. Run Reg-suit locally
Run the site’s build and capture steps first, then invoke Reg-suit from the project root so its configured paths resolve as expected:
npm run build
# Start your static preview server in another process.
node scripts/capture.mjs
npx reg-suit run
The run command syncs expected images, compares them, publishes results through configured plugins, and can notify through configured notifier plugins. For a first run, inspect the generated HTML report and confirm that the expected images are the baseline you intended. If no prior baseline exists, follow the configured publisher and key-generator workflow to establish one.
7. Add the sequence to GitHub Actions
The essential order is checkout, install, build, start the preview server, capture screenshots, then run Reg-suit. The official README’s GitHub Actions example uses a full-history checkout (fetch-depth: 0), sets up Node.js, installs dependencies, and runs Reg-suit. This compact workflow illustrates the sequence; adapt the Node.js version, build command, server command, and credentials to your project and current plugin versions.
name: visual-regression
on: [pull_request]
jobs:
compare:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: 22
cache: npm
- run: npm ci
- run: npm run build
- name: Start static preview server
run: npm run preview -- --host 127.0.0.1 &
- name: Capture pages
run: node scripts/capture.mjs
- name: Compare screenshots
run: npx reg-suit run
Confirm the preview server is ready before capture; a fixed short delay or, preferably, a readiness check can prevent a race between startup and navigation. If the Git-hash plugin cannot determine a base because CI checks out a detached HEAD or omits branch history, follow the branch-checkout workaround documented by Reg-suit and ensure the base commit is available. If using a publisher, provide its credentials through your CI secret mechanism and grant only the permissions required by your deployment policy. Notifications through supported notifier plugins are optional; get capture, baseline selection, and report generation working first. Reg-suit README and CI notes
Or skip the browser setup
You can generate the screenshot inputs with ScreenshotNeo, a screenshot API and MCP server from Yorker Media, then point Reg-suit at the returned image files. See the ScreenshotNeo API docs for request options. For a repeatable capture, keep your URL and capture settings stable and save each response under the same route-based filename.
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://example.com \
-o screenshot/home.webp
ScreenshotNeo accepts cookie and consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers identify the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. The free plan includes 1,000 shots a month with no card; paid plans start at $5 for 3,000 shots. These features can simplify screenshot generation, while Reg-suit still handles image comparison and reports. Sign up for 1,000 free screenshots a month, no card required.
Performance, reliability, and cost
- Performance: capture only the routes and viewport variants that serve your regression goals. Browser startup and page rendering usually dominate this workflow; reuse a browser process for multiple pages, as in the example. Reg-suit exposes a concurrency setting, but check the installed version’s documentation and balance parallelism against CI resource limits.
- Reliability: pin dependencies through your lockfile and use consistent browser and font environments. Check HTTP responses, wait for real readiness signals, close the browser in a
finallyblock, and fail the job if capture does not produce the expected files. Preserve full Git history when using Git-hash keys. - Baseline storage: publisher setup has operational costs and access-control requirements. The research sources confirm plugin support but do not verify current S3 or GCS prices; consult the cloud provider’s current pricing and your retention needs.
- Review cost: comparison noise creates human review work. Stabilize animations, dynamic content, and external resources before loosening thresholds. Keep thresholds tied to deliberate acceptance criteria.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| No actual images found | The capture step did not run, failed, or wrote files to a different directory. | Run capture first, check the output directory, and make core.actualDir match it. |
| All images appear changed | Expected snapshots are missing or the key-generator selected a different baseline. | Inspect the report and selected key; verify branch history, base commit, and publisher configuration before accepting a new baseline. |
| Git key generation fails in CI | Checkout is shallow or detached, so the plugin cannot walk the branch graph or identify a base. | Use full history and ensure the relevant branch/base commit is checked out or fetched, following the Reg-suit CI guidance. |
| S3 access denied | The bucket or CI identity lacks required access, or the configured bucket/path is wrong. | Verify bucket and prefix configuration and review the publisher’s documented IAM actions with your cloud administrator. |
| Screenshots differ on every run | Fonts, animations, timestamps, network content, viewport, browser version, or readiness timing varies. | Fix capture conditions, disable animations where appropriate, wait for fonts and page content, and stub or exclude changing content. |
| Page navigation times out | The page never reaches the chosen network-idle condition or the local server is not ready. | Check server readiness; wait for a stable page selector instead of network idle when the page maintains open requests. |
| Images omit lazy content | Below-the-fold assets were never requested before full-page capture. | Scroll through the page to trigger lazy loading, wait for image completion, then capture; alternatively capture only the intended viewport. |
| Threshold does not behave as expected | The value is misunderstood or differs from the installed version’s configuration. | Confirm the documented 0-to-1 range and that lower values mean greater sensitivity; inspect reports while adjusting incrementally. |
FAQ
Does Reg-suit take website screenshots?
No. Generate the image files with Puppeteer or another capture approach, then configure Reg-suit to read that directory.
Can I run it without a cloud publisher?
Publisher plugins are optional, but your workflow still needs an expected-image strategy. Use the current Reg-suit documentation and plugin options to choose how those images are made available.
Should the threshold always be zero?
No. Zero appears as an example in the demo, not a universal recommendation. Select sensitivity based on the images and review process for your site.
Can I use the screenshot files from an API?
Yes. Reg-suit consumes image files; the capture method can be separate. Save API-generated images to the configured actual-image directory using consistent names and settings.
Primary references
- Reg-suit README: commands, configuration, plugins, CI guidance, and comparison options.
- Official Puppeteer demo: example capture-before-comparison workflow.
- S3 publisher README: bucket setup and documented publisher configuration and permissions.
- Reg-suit project site.


