Visual QA Diff Process in ai-website-cloner-template: How to Compare Screenshots for Pixel-Perfect Clones

The visual QA diff process performs a pixel-by-pixel comparison between the original website and the generated clone at desktop (1440px) and mobile (390px) viewports, using screenshots stored in docs/design-references/ and validated against the Phase 5 checklist defined in .windsurf/workflows/clone-website.md.

The ai-website-cloner-template repository defines a rigorous visual QA diff as the final validation gate in its cloning pipeline. According to the source documentation, this process ensures that the generated Next.js application is visually indistinguishable from the target site by comparing full-page screenshots side-by-side and iterating until zero pixel differences remain.

What Is the Visual QA Diff Process?

The visual QA diff constitutes Phase 5 of the cloning workflow, executed immediately after the builders merge their worktrees and the Next.js app compiles. As documented in .windsurf/workflows/clone-website.md, this phase involves:

  • Capturing full-page screenshots of the original site stored during Phase 1 reconnaissance
  • Capturing identical screenshots of the clone after running npm run build
  • Comparing each section top-to-bottom at 1440px desktop and 390px mobile viewports
  • Tracing every mismatch to its source spec file in docs/research/components/ and rebuilding until the discrepancy resolves

The process enforces pixel-perfect fidelity—any stray margin, incorrect color value, or missing hover state captured in the diff triggers a rebuild of the offending component.

Where the Visual QA Process Is Defined

The canonical definition of the visual QA diff process lives in two locations within the repository:

  • .windsurf/workflows/clone-website.md (line 12): Contains the detailed Phase 5 instructions and the mandatory checklist
  • README.md (section "Assembly & QA", line 94): Provides the high-level pipeline overview mentioning the side-by-side screenshot comparison

Component specifications referenced during the diff are located at docs/research/components/*.spec.md, while screenshot assets reside in docs/design-references/.

How to Capture Screenshots for Comparison

Capturing Original Site Screenshots

During Phase 1 – Reconnaissance, capture baseline screenshots of the live target using a headless browser and store them in docs/design-references/:

// scripts/capture-original.mjs
import { chromium } from 'playwright';

(async () => {
  const browser = await chromium.launch();
  const page = await browser.newPage();
  
  // Desktop viewport
  await page.setViewportSize({ width: 1440, height: 900 });
  await page.goto('https://target-website.com', { waitUntil: 'networkidle' });
  await page.screenshot({ 
    path: 'docs/design-references/original-desktop.png', 
    fullPage: true 
  });
  
  // Mobile viewport
  await page.setViewportSize({ width: 390, height: 800 });
  await page.goto('https://target-website.com', { waitUntil: 'networkidle' });
  await page.screenshot({ 
    path: 'docs/design-references/original-mobile.png', 
    fullPage: true 
  });
  
  await browser.close();
})();

Capturing Clone Screenshots

After building the clone, launch the dev server and capture the same viewports:

// scripts/clone-screenshot.mjs
import { chromium } from 'playwright';

(async () => {
  const browser = await chromium.launch();
  const page = await browser.newPage();

  // Desktop viewport
  await page.setViewportSize({ width: 1440, height: 900 });
  await page.goto('http://localhost:3000', { waitUntil: 'networkidle' });
  await page.screenshot({ 
    path: 'docs/design-references/clone-desktop.png', 
    fullPage: true 
  });

  // Mobile viewport
  await page.setViewportSize({ width: 390, height: 800 });
  await page.goto('http://localhost:3000', { waitUntil: 'networkidle' });
  await page.screenshot({ 
    path: 'docs/design-references/clone-mobile.png', 
    fullPage: true 
  });

  await browser.close();
})();

Run the capture after starting the development server:

npm run dev &
node scripts/clone-screenshot.mjs

How to Compare Screenshots

Manual Side-by-Side Comparison

For manual validation, open the paired PNG files (original vs. clone) side-by-side in any image diff tool. Supported options include ImageMagick, VS Code’s built-in image diff viewer, or GUI tools like Beyond Compare.

Automated Pixel-Match Diff

For CI/CD pipelines, automate the comparison using pixelmatch to generate diff images with highlighted mismatches:

// scripts/visual-diff.mjs
import { readFile } from 'fs/promises';
import pixelmatch from 'pixelmatch';
import { PNG } from 'pngjs';
import { writeFile } from 'fs/promises';

async function diffImages(aPath, bPath, outPath) {
  const [aBuf, bBuf] = await Promise.all([readFile(aPath), readFile(bPath)]);
  const imgA = PNG.sync.read(aBuf);
  const imgB = PNG.sync.read(bBuf);
  const { width, height } = imgA;
  const diff = new PNG({ width, height });

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

  await writeFile(outPath, PNG.sync.write(diff));
  console.log(`✖ ${mismatched} pixels differ – diff saved to ${outPath}`);
}

await diffImages(
  'docs/design-references/original-desktop.png',
  'docs/design-references/clone-desktop.png',
  'docs/design-references/diff-desktop.png'
);

If mismatched returns 0, the visual QA for that viewport passes. Any non-zero value requires revisiting the corresponding component spec in docs/research/components/ and rebuilding.

The Visual QA Checklist

The template enforces a concrete checklist before declaring the clone complete. As defined in .windsurf/workflows/clone-website.md (line 32), the auditor must verify:

  1. Every component has a corresponding .spec.md file
  2. All CSS values originate from getComputedStyle() extraction
  3. Interaction models (hover, scroll, tab) are documented
  4. All component states are captured
  5. Responsive layouts are documented for both viewports
  6. Zero pixel differences exist at desktop (1440px)
  7. Zero pixel differences exist at mobile (390px)

Implement this checklist programmatically using a TypeScript helper:

// scripts/qa-checklist.ts
type ChecklistItem = { label: string; done: boolean };

export const visualQaChecklist: ChecklistItem[] = [
  { label: 'Spec file written for each component', done: false },
  { label: 'All CSS values taken from getComputedStyle()', done: false },
  { label: 'Interaction model documented', done: false },
  { label: 'All component states captured', done: false },
  { label: 'Responsive layouts documented', done: false },
  { label: 'Zero pixel differences at desktop', done: false },
  { label: 'Zero pixel differences at mobile', done: false },
];

export function reportChecklist() {
  visualQaChecklist.forEach(i => console.log(`[${i.done ? 'x' : ' '}] ${i.label}`));
}

Execute node scripts/qa-checklist.ts at the end of Phase 5 to confirm every item is ticked before finalizing the build.

Summary

  • The visual QA diff process is Phase 5 of the ai-website-cloner-template pipeline, defined in .windsurf/workflows/clone-website.md
  • Comparisons occur at 1440px desktop and 390px mobile viewports using screenshots stored in docs/design-references/
  • Pixelmatch or manual tools perform pixel-by-pixel validation between original and clone screenshots
  • The Phase 5 checklist mandates zero pixel differences and complete component documentation before the clone passes QA
  • Discrepancies trace back to docs/research/components/*.spec.md files for deterministic rework

Frequently Asked Questions

What viewport sizes does the visual QA diff process use?

The process mandates validation at two canonical viewports: 1440px width for desktop and 390px width for mobile, as specified in .windsurf/workflows/clone-website.md. These dimensions represent standard breakpoints that ensure responsive fidelity across devices.

Where are the screenshots stored during the visual QA process?

Original site screenshots captured during Phase 1 reconnaissance and clone screenshots taken after npm run build both reside in docs/design-references/. This directory serves as the single source of truth for all visual comparison assets.

Which tools automate the screenshot comparison?

The repository supports Playwright or Puppeteer for headless screenshot capture, and pixelmatch (a Node.js library) for generating diff images with highlighted pixel deviations. For manual review, ImageMagick, VS Code image diff, or Beyond Compare are compatible alternatives.

How do you resolve visual discrepancies found during the diff?

When the diff detects mismatched pixels, trace the visual defect to its source component spec in docs/research/components/<Component>.spec.md. Re-run the extraction script for that component to update the spec with corrected CSS values, rebuild the component, and re-run npm run build until the screenshot comparison returns zero differences.

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 →