You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
We use Chromatic (the paid cloud service from the Storybook maintainers) for visual regression testing β screenshot every story, diff against a baseline, review the difference. The visual-diff capability is genuinely valuable and we want to keep it. The dependency is not:
External paid SaaS + a CHROMATIC_PROJECT_TOKEN secret we must maintain.
CI cost/time β the Publish to Chromatic step (ci.yml) runs a second full build:storybook, uploads it, and snapshots, adding minutes to the already ~30-minute web job (which is currently hitting its timeout-minutes: 30).
Goal: own the visual-regression capability end-to-end on our own infra (Playwright + Cloudflare/R2), drop the paid dependency, and reduce CI time β without losing the "here's what changed, approve it" workflow.
What are the requirements? β
Capture a screenshot of every Storybook story (with a changed-only fast path).
Diff each against a stored baseline and produce a human-reviewable expected / actual / diff artifact.
Deterministic rendering β no false diffs from font/antialiasing/OS differences.
A baseline management + approval flow (how a legitimate visual change gets blessed).
Runs in CI, change-gated; decide blocking vs non-blocking (Chromatic is currently non-blocking via exitZeroOnChanges: true).
No new paid SaaS; permissively-licensed OSS only (all candidates are MIT/Apache-2.0).
Reuse existing infra where possible: Playwright, storybook-static, Cloudflare R2.
Net reduce CI time versus the current Chromatic step.
Closest to Chromatic's review UX; more moving parts
C
Keep Chromatic (status quo)
Chromatic web app
Chromatic cloud
Paid; adds CI time; external dependency
D
Other SaaS (Percy / Applitools)
their UI
their cloud
Still paid β rejected, same downside as C
Legality (see #β discussion): re-implementing the functionality with OSS is fine; only copying Chromatic's code or brand would not be. All candidate tools are MIT/Apache-2.0.
Proposed solution π’
Phase 1 β Option A, behind determinism guarantees.
A Playwright spec reads Storybook's index.json, visits each story's iframe.html?id=<id>, waits for render, and runs await expect(page).toHaveScreenshot().
Run screenshotting only inside the pinned mcr.microsoft.com/playwright Docker image β same version locally and in CI β so baselines are reproducible.
Baselines committed alongside stories; updating them is --update-snapshots in a dedicated PR (the "approval").
In CI, replace the Publish to Chromatic step with this job (change-gated, reusing the Playwright browser cache). Point SB_URL at storybook.soroush.tech instead of Chromatic's output.
Phase 2 (optional) β layer Option B if we want a hosted review report: reg-suit stores baselines in R2, publishes an HTML diff report, and posts a PR comment with pass/fail + link β recovering Chromatic's review ergonomics on our own infra.
Rollout is incremental: run the new job alongside Chromatic until parity is proven, then delete the Chromatic step and CHROMATIC_PROJECT_TOKEN.
Risks & mitigations π¨
Rendering non-determinism (false diffs) β the Configure RenovateΒ #1 risk. Mitigation: containerize screenshotting in the pinned Playwright Docker image; set per-story maxDiffPixelRatio/threshold; disable animations/caret.
Baseline bloat in git (Option A) β many PNGs. Mitigation: keep only chromium + a small viewport set initially; if it grows, move baselines to R2 (Option B).
Approval friction β no hosted "Approve" button. Mitigation: the update-baselines PR is the approval; Phase 2 (reg-suit + PR comment) restores a review report.
Maintenance burden vs SaaS β we now own the tooling. Mitigation: start minimal (Option A); only adopt B if the review UX is missed.
Loss of Chromatic TurboSnap/cloud parallelism β snapshots run on our runners. Mitigation: change-gate stories (only-changed), reuse the browser cache; net CI time should still drop since we remove the extra Storybook build + upload.
Reversibility β low risk: keep the Chromatic step until the self-hosted job reaches parity; rollback is deleting the new job.
Affected area: web
What's the Motivation? π€
We use Chromatic (the paid cloud service from the Storybook maintainers) for visual regression testing β screenshot every story, diff against a baseline, review the difference. The visual-diff capability is genuinely valuable and we want to keep it. The dependency is not:
CHROMATIC_PROJECT_TOKENsecret we must maintain.Publish to Chromaticstep (ci.yml) runs a second fullbuild:storybook, uploads it, and snapshots, adding minutes to the already ~30-minutewebjob (which is currently hitting itstimeout-minutes: 30).SB_URLfor nicer failing-test links) is duplicated.Goal: own the visual-regression capability end-to-end on our own infra (Playwright + Cloudflare/R2), drop the paid dependency, and reduce CI time β without losing the "here's what changed, approve it" workflow.
What are the requirements? β
exitZeroOnChanges: true).storybook-static, Cloudflare R2.What are our options? π‘
toHaveScreenshot()over storiesstorycap+reg-suitLegality (see #β discussion): re-implementing the functionality with OSS is fine; only copying Chromatic's code or brand would not be. All candidate tools are MIT/Apache-2.0.
Proposed solution π’
Phase 1 β Option A, behind determinism guarantees.
storybook-static(already scripted:build:storybook).index.json, visits each story'siframe.html?id=<id>, waits for render, and runsawait expect(page).toHaveScreenshot().mcr.microsoft.com/playwrightDocker image β same version locally and in CI β so baselines are reproducible.--update-snapshotsin a dedicated PR (the "approval").Publish to Chromaticstep with this job (change-gated, reusing the Playwright browser cache). PointSB_URLatstorybook.soroush.techinstead of Chromatic's output.Phase 2 (optional) β layer Option B if we want a hosted review report:
reg-suitstores baselines in R2, publishes an HTML diff report, and posts a PR comment with pass/fail + link β recovering Chromatic's review ergonomics on our own infra.Rollout is incremental: run the new job alongside Chromatic until parity is proven, then delete the Chromatic step and
CHROMATIC_PROJECT_TOKEN.Risks & mitigations π¨
maxDiffPixelRatio/threshold; disable animations/caret.reg-suit+ PR comment) restores a review report.Resources and benchmarks π
Publish to Chromaticstep in.github/workflows/ci.yml;SB_URLconsumed inapps/web/vitest.config.ts.reg-suit(MIT),storycap(MIT), Loki (MIT), BackstopJS (MIT).