Skip to content

Configuration

The cappa.config.ts file controls how screenshots are captured, stored, and reviewed. Config files export a configuration created with defineConfig from @cappa/core.

defineConfig accepts either an object or a function that receives a ConfigEnv object with the current CLI command, mode, and environment variables. This is useful when you need to tailor the configuration in CI environments.

import { defineConfig } from '@cappa/core';
import { cappaPluginStorybook } from '@cappa/plugin-storybook';
export default defineConfig(({ env }) => ({
outputDir: env.CAPPA_SCREENSHOT_DIR ?? 'screenshots',
}));
  • type: string
  • default: 'screenshots'

Folder where screenshots and diffs are written. Cappa will create actual, expected, and diff directories within this folder.

You most probably want to exclude the actual and diff directories from your version control system.

  • type: number
  • default: 2

The number of times to retry a screenshot if it fails. See the Screenshot retries guide for more information.

  • type: number
  • default: 1

The number of parallel browser contexts to use when taking screenshots. Each context can process screenshots independently, significantly speeding up large screenshot runs.

Higher values will consume more system resources (CPU and memory).

  • type: boolean
  • default: true

Controls whether Playwright console events are logged while captures run. Disable this when your stories emit frequent console output and you prefer quieter CLI logs.

Screenshot configuration might get overwritten by plugins or more specific settings, while taking the screenshot.

  • type: { width: number; height: number }
  • default: { width: 1920, height: 1080 }

The viewport to use for the screenshots.

  • type: boolean
  • default: true

Whether to take a full page screenshot. If false, the viewport will be used.

If a height is defined, this setting will supersede the viewport height.

Diff configuration sets global comparison settings for screenshots.

diff supports two algorithms via diff.type:

  • "pixel" (default) for ‘traditional’ pixel-count based comparisons
  • "gmsd" for ‘gradient magnitude similarity deviation’ comparisons. Measures gradient similarity, not just pixel differences. Closer to human perception of similarity.
  • type: "pixel" | "gmsd"
  • default: "pixel"

Selects which algorithm is used when comparing screenshots.

  • type: number
  • default: 0.1
  • range: 0-1

This affects how similar a pixel needs to be to the reference image to be considered the same.

The following options apply when diff.type is "pixel".

  • type: boolean
  • default: false

Whether to include anti-aliased pixels in the diff count. For most users this should be false, because it makes comparisons very sensitive to sub-pixel differences of fonts and other UI elements.

  • type: boolean
  • default: true

Whether to use a fast buffer comparison for identical images. This is a performance optimization that skips the slower image comparison algorithm.

  • type: number
  • default: 0

The maximum number of different pixels before the comparison fails.

  • type: number
  • default: 0
  • range: 0-100

The maximum percentage of different pixels before the comparison fails. This is a relative value, so it is affected by the size of the images. A 100px image with a 10% difference is 10 pixels different, but a 1000px image with a 10% difference is 100 pixels different. On very large full page screenshots this can mean that small changes still slip through.

  • type: boolean
  • default: false

Run a structured interpretation pass after the raw pixel diff. Instead of only telling you where pixels differ, interpretation describes what changed — additions, deletions, color shifts and content changes — grouped into regions, each with a position, a percentage and a confidence score, plus an overall severity (Low / Medium / High) and a human-readable summary.

export default defineConfig({
diff: {
type: 'pixel',
interpret: true,
},
});

When enabled, each changed screenshot gets a diff/<name>.json sidecar next to its diff image:

{
"numDiffPixels": 17904,
"percentDifference": 1.87,
"interpretation": {
"summary": "Moderate visual change detected (1.87% of image, 3 regions). Content changed: 1 region (center).",
"severity": "Medium",
"totalRegions": 3,
"diffPercentage": 1.87,
"width": 1200,
"height": 800,
"regions": [
{
"changeType": "ContentChange",
"position": "center",
"percentage": 0.9,
"bbox": { "x": 420, "y": 300, "width": 360, "height": 200 }
}
]
}
}

The sidecar is read back by cappa status and the review UI:

  • cappa status prints a per-screenshot breakdown of changed screenshots with severity, region count and summary.
  • The review UI shows a severity badge, a summary banner and interactive, color-coded region overlays on the diff view.

The sidecar lives in the diff directory, so it is cleared before each capture and removed when a screenshot is approved.

The following options apply when diff.type is "gmsd".

  • type: 0 | 1
  • default: 0

Downsample factor used by GMSD.

  • type: number
  • default: 170

Stability constant used in the GMSD equation.

Generated PNG files include textual metadata (tEXt chunks) with the comparison details. This includes:

  • cappa.diff.algorithm (pixel or gmsd)
  • the configured diff options used for that comparison, stored as cappa.diff.<option>

You can read these fields in custom tooling to audit how a diff image was produced.

Configuration for the review UI.

  • type: 'light' | 'dark'
  • default: 'light'

Color theme for the review UI. Set to 'dark' for dark mode.

export default defineConfig({
review: {
theme: 'dark',
},
});
  • type: number
  • default: 3000

Port for the review UI server. Set to a different value if port 3000 is already in use.

export default defineConfig({
review: {
port: 4000,
},
});
  • type: (screenshots: FailedScreenshot[]) => void | Promise<void>
  • default: undefined

Runs after a capture completes in CI mode when there are screenshots that failed comparison. CI mode is enabled by running cappa capture --ci or by setting CI=true in the environment. The callback receives an array of failing screenshots, including both relative and absolute paths to the actual, expected, and diff images. Use this hook to upload diff images to object storage or integrate with CI systems.

import { awsS3Upload } from 'aws-sdk';
onFail: async (screenshots) => {
// Upload diff images to your storage provider
for (const screenshot of screenshots) {
if (screenshot.absoluteDiffPath) {
await awsS3Upload(screenshot.absoluteDiffPath);
}
}
}

Browser configuration sets different browser settings for playwright.

  • type: 'chromium' | 'firefox' | 'webkit'
  • default: 'chromium'

The browser to use for the screenshots.

  • type: boolean
  • default: true

Whether to run the browser in headless mode.