Storybook is the de-facto component workshop for React, Vue, and Svelte teams. It catalogs every variant of every component in one place - which makes it the perfect target for visual regression testing. The problem: Storybook itself does not check for visual changes. You still need a screenshot tool that snapshots each story and diffs it against a baseline.
This post walks through wiring Lastest to Storybook so that every story, every variant, and every controlled state becomes a tracked baseline - at zero per-snapshot cost.
Why Storybook needs a visual layer
Storybook gives you isolation: every variant lives in its own controlled environment, free of layout interference from the rest of the app. That same isolation is what makes it the cleanest possible target for visual regression testing. A single story renders deterministically, in the same viewport, with the same controls - exactly the conditions you want for screenshot diffing.
Without a visual layer, Storybook tells you what your components are. With one, it tells you when they change.
How Lastest connects to Storybook
Lastest reads your built Storybook (the static storybook-static output) and treats every story URL as a test target. You point the runner at the directory or hosted URL, and it walks iframe.html?id=… for each story.
lastest storybook-scan \
--storybook-url http://localhost:6006 \
--output suite.json
That command produces a suite where each story becomes a tracked test. From there, every CI run snapshots every story and compares against the baseline.

Capture every variant, not just the happy path
The biggest win is coverage. Most teams write Cypress or Playwright tests for the primary button. Almost nobody covers the disabled, loading, hover, focus, and icon-only variants. Storybook already documents them - visual testing now guards them.

Three patterns we recommend:
- Use Controls to fan out states - generate a story per meaningful prop combination instead of relying on a single "all variants" page.
- Pin stories deterministically - freeze dates, randomness, and animation start times in your
preview.ts. Visual tests are only as stable as the story. - Group by component - Lastest lets you organize tests into suites that mirror your story tree, so a regression in
Button/*shows up as one collapsible group instead of six unrelated failures.
Theme and viewport coverage
Storybook addons like @storybook/addon-themes and @storybook/addon-viewport let you switch presentation. Lastest reads those args and captures a snapshot per combination. Pair that with three diff engines (pixel, structural, perceptual) and you can use perceptual diffs for the full theme matrix and pixel-perfect diffs for individual icon stories.
CI workflow
Build Storybook, hand the static directory to Lastest, run the suite, post a PR comment with the diff link.
- run: pnpm build-storybook
- run: lastest storybook-scan --static-dir storybook-static --output suite.json
- uses: las-team/lastest/action@main
with:
suite: suite.json
server-url: ${{ secrets.LASTEST_SERVER_URL }}
runner-token: ${{ secrets.LASTEST_RUNNER_TOKEN }}
No per-snapshot quota. No story-count tier. Every variant gets the same treatment as the happy path - which is the only way visual testing actually catches the bugs that ship.