Skip to content

Project

Visual review desktop app

Ten minutes was generous. Catching changes is the part the report does well; what it cannot do is tell you which of them you meant. Halfway through a component refactor plenty of them are deliberate: the markup moved because I moved it, and those baselines want updating rather than fixing. Every failure is therefore one small decision, regression or new normal, and not one of them is hard. There are just several hundred, and each needs a person to look at it.

It was tempting to rediscover fire. I managed to stay on course and build only the missing half: the approval pipeline, sitting on top of the JSON report Playwright was already writing. No runner, no reporter, no second source of truth about what failed.

What that leaves is an interface. Failures grouped by site, diff and expected and actual side by side or under a before-after slider, a list view for when you are just grinding through a batch, and no, later or yes on each screenshot. Approvals collect in a queue, and one button writes them back as baselines and pushes them to R2. Essentially a self-hosted, single-user Chromatic, for an audience of one.

The review app: failures grouped by site, each with diff, expected and actual, and no/later/yes controls
Two failures, one site. Diff, expected and actual per screenshot, and three keys to get through them.

The app loads the current report into state, and the workflow runs until every regression is judged. Screenshots arrive over a custom review:// protocol rather than file://, mostly so the renderer can pull images off local disk without being handed the whole filesystem.

It is a great deal of machinery for what is, honestly, an image viewer with two buttons. But it turned the worst part of the refactor into the part I stopped thinking about. Given enough time — trial and error, I mean — I wonder whether it could mature enough for a public repo of its own.

The commit queue panel holding one approved screenshot, with a Push to R2 button
Approvals collect in a queue. One button writes them back as baselines and pushes.
ElectronReactMUIIPC