Scale

Baseline strategies for monorepos and multi-app teams

As visual testing scales across teams and applications, baseline management becomes the bottleneck. Here's how to organize baselines without creating chaos.

Baseline anti-patterns

Most baseline problems stem from unclear ownership. When nobody knows who's responsible for a baseline, it either gets ignored or becomes everyone's problem.

One baseline for everything

A single set of baselines across all apps means one team's changes trigger reviews for everyone. Ownership becomes unclear.

No clear ownership

When baselines are shared, nobody feels responsible. Updates get approved without scrutiny or ignored entirely.

Branch baseline chaos

Feature branches with their own baseline updates conflict when merged. Resolving baseline conflicts is tedious and error-prone.

Stale baselines

Baselines that nobody updates become useless. Tests pass because they compare against outdated expectations.

These patterns emerge naturally in growing organizations. Fixing them requires intentional structure.

Branch baseline strategies

How do baselines relate to git branches? This question causes more confusion than any other in monorepo visual testing.

Main branch as source of truth

Baselines live only on main. Feature branches compare against main's baselines. Updates happen as part of the merge process.

PR-based baseline updates

Baseline changes are proposed in PRs alongside code. Reviewers approve both the code and the visual changes together.

Ephemeral branch baselines

Feature branches can have temporary baselines for development, but they're discarded on merge. Only main baselines persist.

The safest approach: main is the source of truth. Feature branches propose changes. Baselines are updated atomically with the code that changes them.

PR-based approval workflow

Baseline updates should be part of normal code review, not a separate process:

  • Code changes and visual changes together: Reviewers see both in the same PR
  • Visual diffs in CI: Automated comments showing what's changed
  • Explicit approval: Baseline updates require sign-off, not auto-acceptance

This mirrors how teams already review code. For detailed workflow patterns, see visual diff approval workflows.

Organizing baselines by ownership

Directory structure should reflect ownership, not just code structure:

By application

Each app in the monorepo has its own baseline directory. Teams own their app's baselines completely.

By team

Baselines are organized by owning team, not by code location. Works when teams own multiple apps.

By component vs integration

Separate baselines for component-level tests (Storybook) and integration tests (Playwright). Different update cadences.

Example directory structure
baselines/
├── apps/
│   ├── marketing-site/
│   │   ├── homepage-desktop.png
│   │   ├── homepage-mobile.png
│   │   └── pricing-desktop.png
│   ├── dashboard/
│   │   ├── login-desktop.png
│   │   └── settings-desktop.png
│   └── docs/
│       └── article-desktop.png
├── packages/
│   └── design-system/
│       ├── button-default.png
│       ├── button-hover.png
│       └── input-focus.png
└── CODEOWNERS

Use CODEOWNERS to enforce that the right team reviews changes to their baselines.

Component vs page-level baselines

Component baselines (Storybook)

Isolated, fast, stable. Changes are localized. Best for design system teams and shared components.

Page baselines (Playwright)

Integration-focused, slower, more realistic. Changes cascade across pages. Best for critical user flows.

Combining both

Component tests catch isolation regressions quickly. Page tests catch integration issues. Different baseline strategies may apply to each.

In monorepos, you often have both: a shared design system with component baselines, and multiple apps with page-level baselines. They need different management strategies:

  • Component baselines: Owned by the design system team. Updated when components change.
  • Page baselines: Owned by app teams. Updated when pages change.
  • Cascading updates: When a component changes, app baselines may need updating too.

For component-level strategies, see Storybook visual regression testing. For baseline management fundamentals, see visual testing baseline management.

Naming conventions

Good naming makes baselines self-documenting. Bad naming makes them a mystery.

Include app/package name

baselines/app-name/component-name.png makes ownership clear at a glance.

Include viewport

button-desktop.png, button-mobile.png prevents confusion when testing multiple breakpoints.

Include variant/state

button-hover.png, button-disabled.png captures what the baseline represents.

Avoid generated names

Hashes and auto-generated names make baselines harder to understand and review.

When someone sees a failing test, they should know immediately what it's testing and who owns it.

Storage considerations

Baselines are binary files. They don't diff well in git and can bloat repositories. Options:

  • Git LFS: Store baselines in Large File Storage. Keeps the main repo small.
  • External storage: S3, GCS, or similar. Reference by hash in the repo.
  • Tool-managed: Many visual testing tools handle baseline storage themselves.

The choice depends on your scale. Small teams can commit baselines directly. Large monorepos need external storage.

Handling merge conflicts

Baseline conflicts happen when multiple branches update the same baseline. Strategies to minimize pain:

  • Regenerate on conflict: When baselines conflict, regenerate from main rather than manual merge
  • Small, frequent merges: Long-lived branches accumulate conflicts
  • Avoid baseline changes in shared code: Component changes that cascade to many baselines need coordination

For CI pipeline strategies that handle this gracefully, see visual testing in CI pipelines.

Baseline hygiene checklist

  • Establish clear ownership: every baseline has a team responsible for it
  • Organize baselines by app or team, not in a shared global directory
  • Use main branch as the source of truth for baselines
  • Include baseline updates in PR reviews (code + visual changes together)
  • Name baselines descriptively: app, component, viewport, state
  • Separate component-level and page-level baseline strategies
  • Set up CI to fail fast when baselines are missing or unexpected
  • Document the baseline update process for new team members
  • Periodically audit baselines: remove stale ones, update outdated ones

Related guides

Scaling visual testing? Join the waitlist

Get early access