Skip to content

Migrate from Chromatic

A step-by-step guide for teams switching from Chromatic to pxdiff. Most migrations take under 10 minutes — replace the CLI, swap one env var, and your existing Storybook parameters keep working.

Sign up at pxdiff.com and create an organization and project. Then create an API key and set it as a repository secret named PXDIFF_API_KEY.

Replace the chromatic package with @pxdiff/cli:

Terminal window
npm uninstall chromatic
npm install -D @pxdiff/cli

Or install globally:

Terminal window
npm install -g @pxdiff/cli

Replace your Chromatic project token with a pxdiff API key:

env:
CHROMATIC_PROJECT_TOKEN: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
PXDIFF_API_KEY: ${{ secrets.PXDIFF_API_KEY }}

Replace the Chromatic action with pxdiff/storybook:

- name: Build Storybook
run: npm run build-storybook
- name: Chromatic
uses: chromaui/action@latest
with:
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
- name: pxdiff
uses: pxdiff/storybook@v1
with:
api-key: ${{ secrets.PXDIFF_API_KEY }}
source: ./storybook-static

See Storybook Action reference for all inputs and outputs.

Replace the npx chromatic command:

- run: npm run build-storybook
- run: npx chromatic --storybook-build-dir ./storybook-static
- run: pxdiff storybook ./storybook-static
env:
PXDIFF_API_KEY: ${{ secrets.PXDIFF_API_KEY }}

pxdiff reads chromatic.* parameters as a fallback, so your existing story configuration keeps working without changes:

Chromatic parameterpxdiff equivalentFallback?
chromatic.delaypxdiff.delayYes
chromatic.viewportspxdiff.viewportsYes
chromatic.modespxdiff.modesYes
chromatic.disableSnapshotpxdiff.disableYes
chromatic.cropToViewportpxdiff.cropToViewportYes
chromatic.cssSelectorpxdiff.selectorYes
chromatic.ignoreSelectorspxdiff.ignoreSelectorsYes
chromatic.diffThreshold--threshold flagExtracted, applied per-job

You can migrate parameters to the pxdiff namespace at your own pace, or leave them as-is.

// These both work:
parameters: {
chromatic: { delay: 500 },
}
parameters: {
pxdiff: { delay: 500 },
}

If both namespaces are present, pxdiff takes precedence.

If you use Chromatic’s isChromatic() helper to hide dynamic content during captures, replace the import with pxdiff’s isCapturing():

import { isChromatic } from "chromatic/isChromatic";
import { isCapturing } from "@pxdiff/cli/storybook";
const showClock = !isChromatic();
const showClock = !isCapturing();

isCapturing() checks for the same chromatic=true URL parameter that pxdiff appends to story URLs during capture. It’s SSR-safe and has no dependencies.

Elements marked with data-chromatic="ignore" are hidden during captures, just like data-pxdiff="ignore":

<!-- Both attributes work -->
<div data-chromatic="ignore">dynamic content</div>
<div data-pxdiff="ignore">dynamic content</div>
ChromaticpxdiffDescription
BuildCaptureA set of screenshots taken at a point in time
TestDiffComparing a capture against baselines
AcceptApprovePromoting a screenshot to become the new baseline
BaselineBaselineThe expected screenshot for comparison
CHROMATIC_PROJECT_TOKENPXDIFF_API_KEYCI authentication
chromatic.config.json(none)pxdiff uses CLI flags and env vars only
npx chromaticpxdiff storybookCLI entry point (auto-diffs after capture)
chromaui/actionpxdiff/storybookGitHub Action
  • Approvals and baselines — approve snapshots in the review UI, and they become baselines for future diffs. Carry-forward works automatically for snapshots not captured in the current run.
  • GitHub check runs — pxdiff creates status checks on your pull requests, just like Chromatic.
  • Pixel-level diffing — pxdiff uses the same diffing library (pixelmatch) at the same threshold (0.063) as Chromatic. Your diffs will look identical.
  • Managed browser fleet — screenshots are captured in cloud Chromium browsers, not on your CI runner. Results are deterministic across environments. Captures take a few minutes regardless of snapshot count — same as Chromatic.
  • Interaction testing — Storybook play functions run to completion before capture.
  • One workflow, not two — Chromatic splits visual testing into “Tests” (per-snapshot approvals that update baselines) and “Reviews” (all-or-nothing approvals that don’t update baselines). pxdiff has one workflow: every diff lets you approve snapshots individually, and approvals always update baselines. No mode to choose, no confusion.
  • Stacked PRs and flexible baselines — Chromatic can’t resolve baselines when an intermediate branch is missing a capture, making stacked PRs painful — you’d need to run Chromatic on every commit in the stack to keep baselines connected. pxdiff resolves baselines from the merge-base of any ref, so stacked branches work naturally without extra captures.
  • Pay-as-you-go pricing — pxdiff charges per screenshot rather than monthly tiers with overage fees. You add funds and spend them as you go. No surprise bills.
  • Change detection (TurboSnap-equivalent)pxdiff storybook --only-changed traces the Storybook module graph from a --stats-json build and skips unchanged stories, carrying their baselines forward automatically. Same approach as Chromatic’s TurboSnap, same bail conditions (shallow clones, config changes, lockfile changes). Requires actions/checkout with fetch-depth: 0 so the baseline commit is in git history. Storybook integration only — Ladle’s Vite-based build doesn’t emit a compatible module graph. See the Storybook guide for details.
  • First-class local modepxdiff storybook --port 6006 (or pxdiff ladle --port 61000) captures against your running dev server in a local Linux Docker container, with pixel-identical results to CI. No static build, no addon, no Storybook plugin to install — just point at the port your dev server is already on. Or run against a static build with pxdiff storybook ./storybook-static to keep the build step. Chromatic’s equivalent is its Storybook addon; pxdiff exposes the same workflow from the CLI, for both Storybook and Ladle.
  • No config file — pxdiff doesn’t use a config file. All configuration is via CLI flags and environment variables.
  • Framework-agnostic — pxdiff isn’t limited to Storybook. You can test any URL, upload any PNG, or use native Playwright and Vitest plugins.

Common Chromatic CLI flags and their pxdiff equivalents:

ChromaticpxdiffNotes
--project-tokenPXDIFF_API_KEY env varpxdiff uses an env var, not a flag
--storybook-build-dirfirst positional argpxdiff storybook ./storybook-static
--auto-accept-changes--auto-baselineSet baselines from captured screenshots (no diff)
--only-changed--only-changedStorybook only. Requires --stats-json build and fetch-depth: 0 checkout. Equivalent to TurboSnap.
--skip--filter (inverted)Filter stories by glob pattern
--exit-zero-on-changes(check exit code)pxdiff exits 0 on pass, 1 on changes
--branch-name--branchOverride detected branch
--patch-build--baseCompare against a specific ref