Skip to content

Pages plugin

The @cappa/plugin-pages package lets you point Cappa at any list of URLs and capture screenshots without having to wire them through other data sources. It is useful for marketing sites, standalone pages, or routes that are easier to address directly.

Add the Pages plugin alongside the Cappa core packages inside your project:

Terminal window
pnpm add -D @cappa/plugin-pages

Configure the plugin inside your cappa.config.ts file and pass a list of pages to capture. Each page entry must contain a url and can optionally define a human‑readable name:

import { defineConfig } from '@cappa/core';
import { cappaPluginPages } from '@cappa/plugin-pages';
export default defineConfig({
outputDir: 'screenshots',
plugins: [
cappaPluginPages({
pages: [
{ url: 'https://example.com', name: 'homepage' },
{ url: 'https://example.com/pricing', name: 'pricing' },
],
}),
],
});
  • pages – Required array of page entries. Each entry must include:
    • url – The URL to navigate to and screenshot.
    • name – Optional, human‑readable name used as the screenshot filename. When omitted, a filename is derived from the URL.

The plugin will throw an error if you forget to pass options or if pages is empty. This helps catch misconfigurations early in CI.

Each page can override how its screenshot is taken using options. You can also set global defaults on the plugin and override them per page when needed.

Use defaults to define screenshot behaviour that applies to all pages unless they override a particular field:

export default defineConfig({
plugins: [
cappaPluginPages({
pages: [
{ url: 'https://example.com', name: 'homepage' },
{ url: 'https://example.com/blog', name: 'blog' },
],
defaults: {
fullPage: true,
viewport: { width: 1440, height: 900 },
omitBackground: false,
mask: ['.cookie-banner'],
},
}),
],
});

Supported defaults (and per‑page overrides) are:

OptionTypeDescription
fullPagebooleanCapture the full scrollable page.
delaynumberMilliseconds to wait before taking the screenshot.
maskstring[]CSS selectors to hide or blur in the screenshot.
omitBackgroundbooleanRender the page with a transparent background.
viewport{ width: number; height: number }Override the viewport for this page.
diffDiffOptionsOverride global diff settings from cappa.config.ts.

Use the options field on individual pages to fine‑tune behaviour:

export default defineConfig({
plugins: [
cappaPluginPages({
pages: [
{
url: 'https://example.com',
name: 'homepage',
},
{
url: 'https://example.com/pricing',
name: 'pricing',
options: {
viewport: { width: 375, height: 812 },
fullPage: false,
mask: ['.tooltip'],
},
},
],
defaults: {
fullPage: true,
},
}),
],
});

In the example above:

  • All pages capture full‑page screenshots by default.
  • The pricing page overrides the viewport and disables fullPage, so the screenshot is constrained to the mobile viewport instead.

Real‑world pages often need additional time before they settle into a visually stable state. The Pages plugin supports a flexible waiting strategy that can be configured globally or per page.

Use wait on the plugin options to define how Cappa should wait after navigating to a URL:

export default defineConfig({
plugins: [
cappaPluginPages({
pages: [{ url: 'https://example.com', name: 'homepage' }],
wait: {
waitForSelector: '#app-ready',
waitForTimeout: 250,
waitForNetworkIdle: true,
waitForStable: true,
},
}),
],
});

wait supports the following fields:

OptionTypeDescription
waitForSelectorstringWait for a specific CSS selector to appear.
waitForTimeoutnumberWait a fixed number of milliseconds after navigation.
waitForNetworkIdlebooleanWait until there are no in‑flight network requests for a short period.
waitForStablebooleanWait until the DOM stops mutating for a period.

When both plugin‑level wait options and per‑page wait options are present, per‑page values take precedence.

Use the wait field on a page to override only what you need:

export default defineConfig({
plugins: [
cappaPluginPages({
pages: [
{
url: 'https://example.com',
name: 'homepage',
},
{
url: 'https://example.com/dashboard',
name: 'dashboard',
wait: {
waitForSelector: '[data-test-id="dashboard-ready"]',
waitForStable: true,
},
},
],
wait: {
waitForNetworkIdle: true,
},
}),
],
});

Here the dashboard page keeps the global waitForNetworkIdle behaviour but adds its own selector‑based and stability checks before capturing.

For each page, the plugin builds a filename from the name you provide. If name is omitted, a filename is derived from the URL instead (e.g. https-example-com-pricing.png). Cappa uses this filename for the actual, expected, and diff images and exposes it in the CLI output and review UI.

This makes it easier to scan screenshots in the UI and to correlate them back to your configuration when diff failures occur.

Since the config file is just a JavaScript file, you can use it to programmatically define the pages to capture.

For example, you could get a sitemap from your website and dynamically generate pages to capture.

import { defineConfig } from '@cappa/core';
import { cappaPluginPages } from '@cappa/plugin-pages';
// simplified example, in reality you would need to parse the sitemap XML
const sitemap = await fetch('https://example.com/sitemap.xml').then(res => res.json());
const pages = sitemap.map((page) => ({
url: page.url,
name: page.name,
}));
export default defineConfig({
plugins: [
cappaPluginPages({ pages }),
],
});