How to Test and Visualize UI Components in a Monorepo
Build a monorepo workflow for component states, browser interaction tests, and visual regression checks, with Storybook, Playwright, Nx, and Turborepo.
A reliable monorepo UI workflow combines three checks: stories make important component states easy to inspect, browser tests verify user-visible behavior, and visual comparisons catch unintended appearance changes. Let workspace tooling run the right Storybook and test tasks for the projects affected by a change.
Storybook, Playwright, Nx, Turborepo, and Chromatic cover complementary parts of this workflow; the documentation does not establish a universal winner. Pick the pieces that fit your framework, package manager, review process, and CI setup.
1. Decide what each check should prove
Separate behavior from appearance so a screenshot diff is not asked to prove that an interaction works.
| Check | Question it answers | Typical place |
|---|---|---|
| Story | Can this state be rendered and inspected consistently? | Storybook or a component gallery |
| Interaction test | Does user behavior produce the expected visible result? | Story interaction test or browser component test |
| Visual regression | Did layout, color, size, or another visible property change? | Screenshot comparison against a reviewed baseline |
Storybook describes component testing as starting from a story, simulating user behavior, and checking the resulting UI and state. Its documentation summarizes the purpose of visual tests as: “Visual tests catch bugs in UI appearance.” See the Storybook testing documentation and visual testing guide.
2. Map the monorepo and its component boundaries
Before adding commands, identify the shared UI package, the applications that consume it, and the package manager and workspace runner already used in CI. Keep stories close to the package that owns the component when that matches the repository’s conventions.
- Find shared components whose behavior or appearance is important across applications.
- List meaningful states for each: default, disabled, loading, error, responsive, and any state that changes behavior or appearance.
- Check whether consuming applications supply themes, tokens, providers, fonts, or routing context required to render those states.
- Choose which checks run for every relevant change and which can be scoped to affected projects.
This state list is a practical starting point, not a prescribed Storybook checklist. Include the cases that represent real supported behavior; avoid stories for arbitrary combinations that users cannot reach.
3. Create stories as repeatable component fixtures
A story should render a component in a named, reproducible state. Use fixtures for data and provide required context through the project’s existing Storybook setup. Keep state setup deterministic: avoid current time, random values, live network responses, or environment-specific assets unless those are part of what the test intentionally covers.
For example, a component might have stories named Default, Disabled, Loading, and RequestFailed. The exact story syntax depends on the installed framework and Storybook version, so follow the version-specific Storybook documentation rather than copying configuration from a different major version.
Stories serve two jobs: they provide a browser-based place to develop and inspect components, and they give interaction and visual checks stable inputs. A story that cannot render independently is often a sign that required dependencies or state have not been made explicit.
4. Test interactions and state transitions
Use interaction tests for important user flows: submitting a form, opening a menu, dismissing a dialog, selecting a tab, or showing an error after a failed action. Assert what a user can observe, such as a message, changed button state, or visible content, rather than implementation details that can change without changing behavior.
Storybook’s documented pattern associates interaction behavior with stories, so a state can be both inspected and exercised. Keep tests focused: cover meaningful transitions and edge cases, but do not duplicate every assertion already made by lower-level unit tests.
For components that need a real browser environment, Playwright component testing mounts components in a browser through a story gallery served by its development server. Playwright explains: “Tests run in Node.js while components run in a real browser: real clicks are triggered, real layout is executed, visual regression is possible.” Read the Playwright component testing guide and verify its current framework support before adopting it.
5. Add visual regression checks where appearance matters
A visual check compares a rendered story screenshot with an earlier baseline. It can reveal unwanted changes to layout, color, size, spacing, or contrast that behavior assertions may not detect. It does not tell you whether a change is wrong: intended redesigns also produce differences, so a person should review and update baselines deliberately.
- Select representative stories for components whose appearance has meaningful product impact.
- Make rendering conditions consistent: viewport, browser, fonts, data, theme, and animation behavior.
- Run the capture and comparison in the same environment used to create or approve the baseline.
- Review changed output. Accept a new baseline only when the change is intended and the resulting UI is correct.
Do not treat every changed source file as a visible regression, and do not automatically approve every changed image. Storybook’s visual testing documentation describes screenshot-based comparison; product behavior and review controls depend on the chosen workflow.
6. Wire the workflow into Nx or Turborepo
Nx
Nx’s Storybook integration creates project targets to serve, build, and test Storybook. Its documented test runner needs either a served Storybook or a published URL, so CI must make that prerequisite available before invoking the test task. The Nx documentation calls Storybook “a development environment for UI components.” Check the current Nx Storybook integration documentation and its compatibility guidance for the versions in your workspace; the research source observed support for Storybook 8 and 9.
Use the generated project targets as the starting point. Inspect the target configuration and task dependencies instead of assuming a command name or target graph that may not match your Nx version or repository.
Turborepo
Turborepo documents a Storybook workflow alongside a shared UI package. Stories kept with that package can affect cache behavior for dependent tasks. Review task inputs and package boundaries so changes to stories invalidate the tasks that actually depend on them, while unrelated work remains reusable. Follow the Turborepo Storybook guide and adapt it to your workspace layout.
Scope tasks by project and dependency
Use your runner’s project graph and CI change detection to avoid running every visual and browser check for every edit, while ensuring changes to shared tokens, build configuration, or test fixtures reach the consumers that depend on them. Verify this graph behavior in your actual repository. Keep project-specific configuration and visual-service credentials scoped to the projects that need them.
7. Choose local browser checks, hosted visual review, or both
| Workflow | Useful when | Operational detail |
|---|---|---|
| Storybook interaction checks | Tests can be expressed from stories and the team wants an inspectable component workflow. | Use the documented story and play-function pattern for the installed version. |
| Playwright component testing | Real browser rendering and interaction are important to the check. | The component gallery is served by the development server; confirm framework support. |
| Hosted Storybook visual testing | The team wants screenshot review and publishing as part of a hosted workflow. | Plan for project configuration, credentials, baseline review, and CI upload. |
| Workspace targets | Tasks should follow monorepo project and dependency boundaries. | Nx and Turborepo document different integration patterns; configure inputs and prerequisites for your runner. |
For Nx monorepos, Chromatic documents testing projects separately and composing their Storybooks. Its guide also describes TurboSnap and --only-changed for scoped checks. Treat those as documented options, not a guarantee that every repository can use them without configuration. See Chromatic’s monorepo guide. No neutral comparison in the research establishes a price, speed, or accuracy winner among these approaches.
8. Example CI sequence
The exact commands depend on the repository’s package manager, framework, installed runner, and generated targets. A robust sequence is:
- Install from the lockfile with the package manager used by the repository.
- Build the shared UI package and any prerequisite applications or Storybook configuration.
- Start or publish the Storybook URL required by the selected test runner.
- Run interaction or browser component tests for affected projects.
- Run visual capture and comparison for the selected stories or projects.
- Upload hosted visual results if applicable, then make baseline changes reviewable in the normal code review.
Keep these steps as workspace tasks where possible so local development and CI use the same project configuration. A CI task should fail clearly when its Storybook server or published URL is missing, rather than silently skipping the browser checks.
9. Troubleshoot common failures
| Symptom | Likely cause | Fix |
|---|---|---|
| Storybook target cannot start | Version mismatch, missing framework configuration, or a project target not generated for this package. | Check the installed Storybook and workspace integration versions, inspect the project target configuration, and follow the current compatibility guide. |
| Test runner cannot reach Storybook | The runner expects a served instance or URL that CI has not started or published. | Add an explicit server or publish prerequisite and pass the correct URL using the documented configuration. |
| Story renders locally but fails in CI | Missing provider, environment variable, font, asset, or fixture; alternatively, the story depends on external network state. | Make dependencies explicit, provide deterministic fixtures and required environment values, and avoid live services in component checks. |
| Screenshot diffs change across runs | Unstable data, animation, timing, browser or font differences, or inconsistent viewport. | Stabilize inputs and rendering conditions; wait for the intended UI state and use the same capture environment for baseline and comparison. |
| A shared-package edit does not trigger the expected task | Project dependency boundaries or task inputs omit relevant files, such as stories or shared tokens. | Review the project graph and cache inputs, then ensure affected consumers and visual tasks depend on the changed files. |
| Many unrelated projects rerun after a story edit | Stories are included in broad task inputs or package dependencies are too coarse. | Inspect cache inputs and dependency boundaries; scope tasks carefully without excluding files that affect rendered output. |
| Visual diff flags an intended redesign | The baseline represents the previous appearance. | Review the rendered change and approve an updated baseline only after confirming the new appearance is intentional. |
| Browser test passes but the component still looks wrong | Behavior assertions do not cover appearance, or visual capture does not include the affected state. | Add a representative story and visual check for that state, then review the captured baseline. |
10. Performance, reliability, and cost considerations
Browser rendering and screenshot comparison add work beyond a fast unit-test runtime. Keep the visual suite focused on representative states, scope tasks using project dependencies where the runner supports it, and avoid rebuilding or capturing unrelated projects. The sources describe these orchestration options but provide no neutral benchmark, so measure CI time and cache behavior in your own repository.
Reliability depends on reproducible rendering: stable fixtures, explicit fonts and providers, controlled viewport and browser versions, and correct task inputs. A cache can make a task faster only when its inputs represent all files and configuration that can affect the output. Periodically review whether shared tokens, stories, and build configuration invalidate the relevant tasks.
Account for the operational cost of whichever visual workflow you choose: browser resources in CI, baseline review time, hosted service plans if applicable, and maintaining project tokens or secrets. The research dossier does not establish comparative pricing, so check current vendor documentation before budgeting.
11. Or skip the browser setup
For screenshots of a deployed page or a public Storybook, ScreenshotNeo provides a website screenshot API and MCP server. It is useful for page captures and visual references; it does not replace component stories, interaction assertions, or baseline review in your test workflow. See the ScreenshotNeo API documentation.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
const image = Buffer.from(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', image));
Cookie banners, popups, and chat widgets are removed before the shot. Bot checks, blank pages, and failed loads are never billed. An MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Sign up for free and capture your first screenshots.
FAQ
How do I test a component library in a monorepo?
Give important states stable stories, test key user interactions in a browser, and scope those tasks through the workspace project graph. Add screenshot comparison for components where appearance changes need review.
How do I catch visual regressions in Storybook?
Capture selected stories, compare them with a known baseline under consistent rendering conditions, and review differences before approving baseline updates.
Do I need both Playwright and a hosted visual testing service?
No. Choose based on whether you need real-browser component interaction, hosted screenshot review, or both. The documented workflows are complementary; the research does not identify one required combination.
Should every component state have a visual baseline?
No. Prioritize states whose appearance matters and where a change could affect users. Keep interaction assertions for behavior and use visual comparisons for appearance.


