Visual Testing for Static Sites: No Tests Required

Got a static site? Now you can visually test every page without writing tests. The new Static Site SDK auto-discovers pages, captures screenshots, and handles comparisons. Works with Gatsby, Astro, Jekyll, Next.js, and any static site generator.

If you’re building a static site, visual testing has been… awkward. You either skip it entirely or cobble together a test suite just to capture screenshots. Neither option feels right.

We built a Static Site SDK that fixes this. Point it at your build directory and it handles the rest - page discovery, screenshots, comparisons, the whole workflow.

How It Works

The SDK discovers your pages automatically. It looks for a sitemap.xml, scans HTML files, or both. Then it spins up a local server, captures screenshots across viewports, and sends them to Vizzly.

Here’s what that looks like:

# Build your static site first
npm run build

# Capture screenshots from the build
vizzly static-site ./dist

That’s it. No test files, no configuration, no manually listing every page.

What Gets Discovered

The SDK finds pages using two methods:

Sitemap.xml parsing - If your static site generator creates a sitemap (most do), the SDK extracts all the URLs automatically.

HTML file scanning - Walks through your build directory and finds every .html file, converting file paths to proper URLs.

Both methods work together. If you’ve got a sitemap, great. If not, HTML scanning has you covered.

Multi-Viewport Screenshots

Static sites need to work everywhere - desktop, tablet, mobile. The SDK captures screenshots at multiple viewports by default.

Want custom viewports? Configure them:

// vizzly.config.js
export default {
  staticSite: {
    viewports: [
      { name: 'mobile', width: 375, height: 667 },
      { name: 'tablet', width: 768, height: 1024 },
      { name: 'desktop', width: 1920, height: 1080 },
    ],
  },
};

Or pass them via CLI:

vizzly static-site ./dist --viewports "mobile:375x667,desktop:1920x1080"

Each page gets captured at every viewport. You’ll catch responsive layout issues before they ship.

Interaction Hooks for Dynamic Content

Static sites aren’t always static. You’ve got JavaScript, lazy-loaded content, animations that need time to settle.

Interaction hooks let you interact with pages before screenshots:

// vizzly.static-site.js
export default {
  interactions: {
    'blog/*': async (page) => {
      // Wait for blog content to load
      await page.waitForSelector('.blog-content');
    },
    'products/*': async (page) => {
      // Click to reveal product details
      await page.click('.view-details');
      await page.waitForSelector('.product-modal');
    },
  },
};

Patterns support glob syntax (blog/*, docs/**). The SDK matches pages to hooks and runs them before capturing screenshots.

Pattern-Based Filtering

Got hundreds of pages but only want to test specific sections? Filter them:

# Only test blog pages
vizzly static-site ./dist --include "blog/**"

# Test everything except 404s
vizzly static-site ./dist --exclude "**/404.html"

Combine patterns for precise control:

// vizzly.config.js
export default {
  staticSite: {
    include: 'blog/**',
    exclude: '**/draft-*.html',
  },
};

Works with Your Static Site Generator

This SDK doesn’t care how you build your site. It just needs HTML files.

Gatsby:

gatsby build
vizzly static-site ./public

Astro:

npm run build
vizzly static-site ./dist

Jekyll:

bundle exec jekyll build
vizzly static-site ./_site

Next.js Static Export:

npm run build
vizzly static-site ./out

Same pattern works for Hugo, Eleventy, VuePress, Docusaurus - any generator that outputs HTML.

Local TDD Workflow

Here’s where this gets useful. When you’re building a static site, you make changes, rebuild, check the output. Rinse and repeat.

Now add visual validation to that loop:

# Start Vizzly TDD mode
vizzly tdd start

# In another terminal, rebuild and capture screenshots
npm run build && vizzly static-site ./dist

The SDK detects the TDD server automatically. Screenshots get compared locally, diffs show up instantly in your browser at http://localhost:47392.

No context switching. You code, rebuild, see exactly what changed visually. Accept or reject changes from the UI.

CI/CD Integration

The same SDK works in CI. Set a VIZZLY_TOKEN environment variable and screenshots upload to the cloud for team review:

# .github/workflows/visual-tests.yml
name: Visual Tests

on: [push, pull_request]

jobs:
  visual-tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-node@v3

      - run: npm install
      - run: npm run build

      - run: npx vizzly static-site ./dist
        env:
          VIZZLY_TOKEN: ${{ secrets.VIZZLY_TOKEN }}

The SDK detects the token and switches to cloud mode. Your team gets automatic visual review on every PR.

Configuration Priority

Configuration merges in this order:

  1. Default settings (sensible defaults, works out of the box)
  2. vizzly.config.js (project-level configuration)
  3. vizzly.static-site.js (interaction hooks and page overrides)
  4. CLI flags (highest priority, overrides everything)

This layering means you can set project defaults but override them per-page or per-run as needed.

Per-Page Overrides

Sometimes specific pages need different treatment:

// vizzly.static-site.js
export default {
  pages: {
    '/': {
      viewports: ['mobile', 'desktop'], // Only test key viewports for homepage
    },
    '/pricing': {
      screenshot: { fullPage: true }, // Capture entire pricing page
    },
  },
};

Per-page config overrides global settings. Useful for special cases without cluttering your main config.

Parallel Processing

Static sites can have hundreds or thousands of pages. The SDK processes them in parallel:

vizzly static-site ./dist --concurrency 5

Default is 3 parallel pages. Bump it higher for faster captures, or lower it if you’re hitting resource limits.

Why This Matters

Visual testing shouldn’t require test infrastructure. If you’re generating HTML, you should be able to validate it visually without writing Playwright scripts or maintaining a test suite.

This SDK makes visual testing as simple as your build process. Point it at HTML, get screenshots, see what changed. Local iteration stays fast. Team review happens automatically in CI.

It’s visual quality integrated into your static site workflow, not bolted on afterward.

Try It

Install the SDK:

npm install @vizzly-testing/static-site

Capture screenshots from your build:

vizzly static-site ./dist

The plugin auto-discovers pages, handles viewports, and integrates with both local TDD and cloud builds.

Static Site SDK docs →

Ready to improve your visual workflow?

Start using Vizzly today and bring visual regression testing into the workflow described in this article.