How to Perform a Visual QA Diff Between Original and Cloned Websites

Capturing screenshots of both the original target site and the locally hosted Next.js clone, then comparing them pixel-by-pixel using tools like Playwright and pixelmatch, is the core method for visual QA diff in the AI Website Cloner Template.

The AI Website Cloner Template is a full-stack Next.js project generator that mirrors target websites through an automated pipeline. Performing a visual QA diff between original and cloned websites ensures that the generated components accurately replicate the source design across all device viewports. This verification happens during the "Assembly & QA" phase, where agents use browser automation to detect visual regressions before finalizing the build.

The Visual QA Pipeline in AI Website Cloner Template

According to the repository's README.md (lines 94-95), the pipeline reaches "Assembly & QA" after the parallel build phase completes. This stage is where the visual comparison happens, validating that the cloned Next.js output matches the original site's appearance.

Reconnaissance Phase: Baseline Capture

During the initial reconnaissance step, the system captures screenshots of the original website at every viewport size (desktop, tablet, and mobile). These baseline images are stored in docs/design-references/ and serve as the authoritative reference for all subsequent comparisons.

Assembly & QA Phase: Pixel Comparison

After the components are generated and the Next.js app is built, the pipeline launches the local development server (npm run dev). The same viewport configurations used during reconnaissance are applied to render the cloned site, producing a second set of screenshots. A pixel-by-pixel diff algorithm then highlights discrepancies between the original and cloned image sets.

Implementing the Visual QA Diff Script

The repository implements visual QA through a TypeScript script that leverages Playwright for browser automation and pixelmatch for image comparison. Below is the complete implementation that reproduces the agent's QA workflow:

// scripts/visual-qa.ts
import { chromium, expect } from '@playwright/test';
import pixelmatch from 'pixelmatch';
import { readFileSync, writeFileSync } from 'fs';
import { PNG } from 'pngjs';

// Helper to compare two PNG buffers
function diffImages(imgA: Buffer, imgB: Buffer, outPath: string) {
  const pngA = PNG.sync.read(imgA);
  const pngB = PNG.sync.read(imgB);
  const { width, height } = pngA;
  const diff = new PNG({ width, height });

  const mismatched = pixelmatch(
    pngA.data,
    pngB.data,
    diff.data,
    width,
    height,
    { threshold: 0.1 }
  );

  writeFileSync(outPath, PNG.sync.write(diff));
  return mismatched;
}

// Main routine – runs for a given URL and a list of viewports
async function runVisualQA(originalUrl: string, localUrl: string) {
  const browser = await chromium.launch();
  const page = await browser.newPage();

  const viewports = [
    { name: 'desktop', width: 1440, height: 900 },
    { name: 'tablet', width: 768, height: 1024 },
    { name: 'mobile', width: 375, height: 667 },
  ];

  for (const vp of viewports) {
    await page.setViewportSize({ width: vp.width, height: vp.height });

    // 1️⃣ Original site screenshot
    await page.goto(originalUrl, { waitUntil: 'networkidle' });
    const origPath = `tmp/orig-${vp.name}.png`;
    await page.screenshot({ path: origPath, fullPage: true });

    // 2️⃣ Cloned site screenshot
    await page.goto(localUrl, { waitUntil: 'networkidle' });
    const clonePath = `tmp/clone-${vp.name}.png`;
    await page.screenshot({ path: clonePath, fullPage: true });

    // 3️⃣ Diff
    const diffPath = `tmp/diff-${vp.name}.png`;
    const mismatched = diffImages(
      readFileSync(origPath),
      readFileSync(clonePath),
      diffPath
    );

    console.log(
      `${vp.name}: ${mismatched} pixel differences – diff saved to ${diffPath}`
    );
  }

  await browser.close();
}

// Example usage (run after `npm run dev`)
// Replace with the real target and the local dev URL.
runVisualQA('https://example.com', 'http://localhost:3000');

The diffImages function reads both PNG buffers, instantiates a new PNG canvas for the diff output, and invokes pixelmatch with a threshold of 0.1 to detect perceptible differences while ignoring minor anti-aliasing variations.

Running Visual QA Locally and in CI

You can execute the visual QA diff through several methods depending on your environment:

  • Local development: Run npm run dev && ts-node scripts/visual-qa.ts to start the cloned app and immediately capture comparison screenshots for desktop, tablet, and mobile viewports.

  • CI/CD integration: Add a step in .github/workflows/ci.yml that executes ts-node scripts/visual-qa.ts after npm run build. This fails the workflow if the pixel difference exceeds your defined threshold, guaranteeing visual fidelity before merging pull requests.

  • Diff-only mode: Execute node scripts/visual-qa.js --mode diff-only to skip launching the dev server when baseline screenshots are already stored in docs/design-references/.

Key Files and Configuration

Understanding the repository structure helps you locate and customize the visual QA components:

  • README.md (lines 94-95): Documents the "Assembly & QA" pipeline stage where visual diff occurs.
  • docs/design-references/: Directory containing the original site screenshots that serve as the baseline for comparison.
  • src/app/layout.tsx and src/app/page.tsx: Core Next.js entry points rendered during the screenshot capture of the cloned site.
  • AGENTS.md: Source-of-truth configuration file where the visual QA step is defined as part of the agent skill workflow.

Summary

  • The AI Website Cloner Template performs visual QA diff during the "Assembly & QA" phase by comparing original site screenshots against the generated Next.js output.
  • Playwright handles browser automation and screenshot capture, while pixelmatch provides the pixel-by-pixel comparison algorithm.
  • Baseline images are stored in docs/design-references/ and compared against tmp/ outputs generated from the local dev server running at localhost:3000.
  • The scripts/visual-qa.ts implementation supports desktop (1440×900), tablet (768×1024), and mobile (375×667) viewports by default.
  • Integrating the script into CI pipelines ensures visual regressions fail builds before deployment.

Frequently Asked Questions

What tools does the AI Website Cloner Template use for visual QA diff?

The template uses Playwright for browser automation and screenshot capture, combined with pixelmatch (or alternatively looks-same) for the actual image comparison. These tools run within a TypeScript script that launches Chromium in headless mode to render both the original and cloned sites consistently.

Where are the baseline screenshots stored for comparison?

Original site screenshots captured during the reconnaissance phase are stored in docs/design-references/. These serve as the immutable reference points that the cloned site screenshots are compared against during the QA phase.

How do I adjust the sensitivity of the visual diff detection?

Modify the threshold parameter in the pixelmatch call within scripts/visual-qa.ts. The default value of 0.1 ignores minor anti-aliasing differences; lowering this value increases sensitivity to catch smaller visual discrepancies, while raising it permits more tolerance for rendering variations.

Can I run visual QA diff in a CI/CD pipeline?

Yes. Add a step to your workflow file (e.g., .github/workflows/ci.yml) that runs ts-node scripts/visual-qa.ts after npm run build. Configure the script to exit with a non-zero status code when mismatched pixels exceed your tolerance level, which will fail the build and prevent deployment of visually inaccurate clones.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →