Juxtapose

Documentation

Visual tests for
your Storybook.

Capture your stories, compare them with approved baselines, and review the screenshot and DOM changes. Start locally; no cloud account is needed.

These steps use an existing Storybook project and Node.js 22.2 or later. The CLI is @juxtapose/cli; its command is jux. The unrelated npm package named jux is not this tool.

1. Install the CLI and addon

Choose the package manager your project uses. Run the command in the package that contains your Storybook.

npm
npm install --save-dev @juxtapose/cli @juxtapose/storybook
pnpm
pnpm add -D @juxtapose/cli @juxtapose/storybook
Yarn
yarn add -D @juxtapose/cli @juxtapose/storybook
Bun
bun add -d @juxtapose/cli @juxtapose/storybook

Download the pinned Chrome for Testing browser once:

npx -p @juxtapose/cli jux browser install

The commands below use npx -p @juxtapose/cli jux. With the CLI installed locally, you can use pnpm exec jux, yarn jux, or bun run jux instead. You do not need to install Playwright.

2. Register the Storybook addon

Add @juxtapose/storybook to the existing addons array in .storybook/main.ts or main.js. Keep your other addons and framework settings.

.storybook/main.ts · excerpt
addons: [
  // Your existing addons…
  '@juxtapose/storybook',
],

Restart your Storybook dev server after changing the config. Juxtapose adds a review panel and marks changed stories in the sidebar. Its test-provider integration needs Storybook 8.5 or later. Read about live capture and Run tests.

3. Capture your first baseline

Start from a UI state you want to keep. Build Storybook, then initialize Juxtapose:

npx storybook build --quiet --disable-telemetry --loglevel error
npx -p @juxtapose/cli jux init

init captures and approves the initial baselines. It also writes the project config and updates .gitignore. Review those initial captures before treating them as your reference.

git add juxtapose.config.json juxtapose.manifest.json juxtapose.structures .gitignore

Review git status before committing. juxtapose.structures contains the generated structure sidecars. Baseline hashes and structure belong in Git; captured images stay in the local cache. See the CLI reference for setup options.

4. Change a component, then compare

After an edit, rebuild Storybook and run the comparison:

npx storybook build --quiet --disable-telemetry --loglevel error
npx -p @juxtapose/cli jux run --html

run selects stories affected by your change. Use --all to capture the whole set. A changed, new, or stale story makes the command exit nonzero; that is the review signal.

Open the generated .juxtapose/runs/<run-id>/report.html, or inspect the diffs in the Storybook addon. Fix unexpected changes and capture again. To approve one intended change, use its story ID:

npx -p @juxtapose/cli jux list
npx -p @juxtapose/cli jux approve --story 'button--primary'
npx -p @juxtapose/cli jux check

Replace button--primary with an ID from your project. Approval performs a fresh confirming capture; keep the same build available. Commit the updated manifest and structure sidecars after review.

Give your agent the diff

For a failing story, the handoff command produces a prompt with the comparison evidence:

npx -p @juxtapose/cli jux handoff 'button--primary'

For an agent that supports MCP, Juxtapose also exposes capture, diff, run, and review tools. Follow the MCP setup guide or the CLI agent workflow.

Run the same check in CI

Add these steps after checkout, Node setup, and your project's dependency installation. The GitHub Actions job needs contents: read and pull-requests: write permissions to post PR comments.

GitHub Actions · steps
- run: npx -p @juxtapose/cli jux browser install
- run: npx storybook build --quiet --disable-telemetry --loglevel error
- run: npx -p @juxtapose/cli jux run --comment --html
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- uses: actions/upload-artifact@v4
  if: always()
  with:
    name: juxtapose-report
    path: .juxtapose/runs/*/report.html

Approve baselines on the same OS as your CI runner. macOS and Linux can render different pixels. Restore the approved image cache if you want before/after images in CI reports; hashes and structure alone still identify changes. The full CI guide covers cache setup and platform details.

Hosted review · Early access

Hosted uploads require @juxtapose/cli 0.23.0 or later and a project token from the hosted dashboard. Use the hosted upload guide for setup and retry commands.

Uploading does not approve snapshots or alter the local manifest. Local CLI verdicts use local approvals; hosted review has its own review decisions. Keep project tokens in environment variables or CI secrets, never in config files or command arguments.

Work toward a design reference

Give your agent the reference image or design comp together with intent notes: which layout, text, states, and spacing matter. Render the component at the reference's viewport, scale, and theme before reviewing it. A heading that wraps or a button with the wrong padding is useful feedback for the next edit.

Use captures to inspect each iteration, then approve a rendered baseline when it matches your intent. Juxtapose's current comparisons operate on rendered captures. It does not import Figma files or automatically score an arbitrary design image. After approval, compare each new render with that baseline to catch regressions.

Performance and comparison evidence

Juxtapose reduces repeated work through affected-story selection, exact-hash matches, and warm local browser reuse. Renderer sharing is on by default; warm story switching is a separate opt-in setting. These are different mechanisms, not interchangeable modes.

Start with named DOM changes, then open images where they add context. The report identifies changed elements, properties, and values so the agent can focus its next inspection.

For reproducible measurements, record the story set, viewports, browser and OS, cold versus warm runs, and repeated-run spread. Measure capture, DOM extraction, comparison, and approval separately. See the field-test guide for existing corpus context.

Handle rendering noise explicitly

Use settling and explicit readiness selectors for asynchronous UI. Configure animation and clock freezing where the story needs it; mock changing data or mask a region only when that content is intentionally outside the test.

With shared renderers, a baseline mismatch retries with a cache pulse and then a fresh renderer if needed. Recovery must match the baseline's exact hash. Approval also performs a fresh confirming capture; these protections do not make nondeterministic stories deterministic.

The configuration reference explains project, story, and variant settings. Optional visual equivalence is reported explicitly and does not silently replace the approved baseline.

Go further

  • Configuration — viewports, themes, masks, settling, and visual equivalence.
  • CLI reference — selection, variants, affected runs, and command options.
  • Browser setup — pinned Chrome, custom Chromium, and warm sessions.
  • Packages — CLI, Storybook addon, and adapters.