Vue visual regression testing, without lock-in
Vue visual regression testing: screenshot Vue and Nuxt components through Storybook or Vitest, or point Playwright at your running app, even on a mixed PHP plus Vue stack.

On this page
Visual regression testing works for Vue the way it works for React, because a screenshot captures rendered browser output, not framework internals. By the time a page is on screen it is pixels, and pixels do not know whether Vue, Nuxt, React, or a server-rendered PHP template produced the DOM. That is most of the answer, but the question keeps arriving in different shapes, and each one deserves a straight reply.
The mixed-commit question, four ways
It arrives in four shapes. "The commit usually goes out mixed, PHP and Vue together. In that situation, how would your feature work?" "Does it only work with Vitest? We are on Angular with Jasmine." "I take it yours doesn't depend on the framework at all, or are there limits?" And the micro-frontend version: a Nuxt shell with one module in plain Vue and others in React or Angular, each in its own IDE, where no single agent holds the whole picture and the seam between them is where the bugs live.
The answer to all four is the same. The dependency is on the test framework, not the UI framework. UI Verify captures through Storybook, Vitest browser mode, and Playwright, and each of those already speaks Vue on its own terms.
The Angular question had a second half worth repeating, because it applies to Vue teams on Jest or Jasmine too. A visual test is a separate file next to the component, not a change to the unit tests you already run, so adopting it does not mean touching your existing test infrastructure. The usual reaction once that lands is relief, and it is the reaction I would expect from any team that assumed a visual tool would want to own their test runner.
Three capture paths, none of them Vue-specific
- Storybook stories. Storybook supports Vue, and UI Verify replays a built Storybook by reading its
index.jsonand driving each story's iframe. It never imports your framework. The capture engine has no React dependency; there is nothing in it that could care. - Vitest browser mode. A component test that already renders a Vue component in a real browser becomes a visual test with no new snapshot calls.
- Playwright against a URL. Your running Vue or Nuxt app, a per-branch staging deploy, a PHP page with a Vue island in it. The capture is the real rendered page, whatever drew it.
{
"v": 5,
"entries": {
"invoice--default": {
"type": "story",
"title": "Invoice",
"name": "Default",
"importPath": "./src/components/Invoice.stories.ts"
}
}
}That file looks identical whether the stories behind it are .vue single-file components or React. I will be precise about one thing: we develop and dogfood UI Verify on a React codebase, so React is what gets exercised every day. Vue works because the seam is below the framework, not because there is a Vue integration to maintain. There is no @uiverify/vue package and no adapter to install, on purpose: a per-framework SDK is the lock-in that makes teams nervous, and the browser is a cleaner seam than any framework binding. Skip-unchanged already treats .vue and .svelte files as traceable build inputs when it walks the module graph.
Invoice.vue is plain DOM with scoped-style hashes, the same kind of markup any other framework would leave behind.How do you visual test a mixed PHP and Vue stack?
This is where the Playwright path matters most. Point it at your running app or a staging URL, and it screenshots the rendered page whether that page came from a Blade template, a Vue island, a Nuxt route, or all three on one screen. A single commit that touches PHP and Vue together gets one visual check over the real composed output, instead of two half-checks that miss the seam between them. Backend logic has unit tests and integration tests that tell you it works. The frontend is where a form can submit correctly, pass its interaction test, and still look wrong, with something collapsed or drifted. The screenshot is the only check that sees that, and it does not care which language rendered it.
price to unit_price on both sides but missed one template line, so every line item rendered £NaN while the total stayed right. Each half would pass its own tests; one Playwright screenshot of the composed page failed on 2,301 pixels.Where do you start with Vue visual regression testing?
Start from the capture method you already have. If your Vue components live in Storybook, wire up the Storybook quickstart. If you test components in Vitest browser mode, the Vitest quickstart turns those into visual tests directly. If you have neither but you have a running app, the Playwright quickstart gets you a first capture against a real page in minutes, and for a stack with no component tests at all, visual testing without Storybook is the longer version of that on-ramp.
From there the rest is the same for Vue as for anything else. Baselines resolve against your branch's git ancestry, captures run in the cloud with a frozen clock, frozen animations, seeded randomness, and inlined fonts, and the AI judge reads the PR to tell an intended restyle from a regression. Vue is not a second-class citizen here, and there is no catch hiding in the setup. Pick a capture path, ship a first screenshot, and the framework question answers itself.
Visual test your Vue app today
Screenshot Vue and Nuxt components, or point Playwright at your running app, mixed PHP stack and all. No React and no Vue-specific SDK required.
Start for freeNo credit card required.
Deterministic Playwright captures
Stop real-page diffs that flake without a real change.

