State Machines, Hot Spots, and a Bear: December Vizzly Updates

We shipped a lot this month. User-controlled hot spot regions, real-time SSE updates, a branded CLI with our bear mascot, mobile review UI, and the TDD dashboard picked up the current BearDen-style token language.

The hot spot and automatic approval sections describe features that are no longer part of Vizzly.

December has been busy. Let me catch you up.

Hot Spot Regions: Teaching Vizzly Where to Look

This is the big one. We rebuilt how Vizzly handles build approvals using a state machine, and shipped a feature I’ve been thinking about for months: user-controlled hot spot regions.

Here’s the backstory. Vizzly already learned which areas of your screenshots change frequently — timestamps, user avatars, ad banners — and used that data for auto-approval behind the scenes. But you couldn’t see what it learned. You couldn’t correct it when it was wrong. It was a black box.

Now hot spots are visible. When Vizzly identifies a region that keeps changing across builds, it surfaces it as a candidate. You can confirm it (“yes, that’s the timestamp footer”) or reject it (“no, that’s actually a bug”). Confirmed hot spots continue auto-approving. Rejected ones get flagged for manual review.

The state machine tracks everything: why each comparison was approved (manual, cascade, auto_hot_spot, auto_identical), who approved it, when. Full audit trail. You can even unapprove or unreject if you made a mistake — the system handles the cascade logic properly.

Same smart automation, but now you’re in the driver’s seat.

Real-Time Dashboard with Server-Sent Events

Small change, big impact. The TDD dashboard used to poll for updates every 1-2 seconds. Now it uses Server-Sent Events.

The moment your test captures a screenshot, it appears in the dashboard. No more refreshing. No more “did my test run?” uncertainty. The connection auto-reconnects if it drops, and falls back to polling if SSE isn’t supported.

Under the hood, we eliminated about 90% of the HTTP traffic between your tests and the dashboard. Zero new dependencies — just native EventSource in the browser and fs.watch on the server.

The CLI Got a Facelift

Run vizzly --help now. Go ahead, I’ll wait.

    ʕ□ᴥ□ʔ
   vizzly v0.21.0
   Visual regression testing for UI teams

  Usage  vizzly [options] [command]

  ▸ Core
      upload             Upload screenshots to Vizzly
      tdd                Run tests in TDD mode...

Yeah, we have a bear now. With square eyes to match our logo. His name is… actually, we haven’t named him yet. Suggestions welcome.

But it’s not just cosmetic. We built a complete TUI (Terminal UI) toolkit that follows the same visual review language as the rest of the product. Commands are grouped by category. There’s a Quick Start section with copy-paste examples. And here’s the cool part: dynamic context.

If you’re in a project directory with a config file, the help output shows your TDD server status, which project you’re linked to, and how many baselines you have. Context that actually helps instead of generic placeholder text.

The whole CLI output is cleaner now. Better contrast, properly aligned columns, status badges with color coding. It’s the kind of polish that makes a tool feel professional.

TDD Dashboard: Now with BearDen-Style Tokens

The TDD dashboard now shares the same BearDen-inspired local token language as the marketing site and docs. Same workflow, same review vocabulary, but with a cleaner visual foundation that fits the current product story.

We also redesigned the screenshot list with smart variant grouping. If you capture the same screenshot across multiple viewports, they collapse into a tree you can expand. Way easier to navigate when you’ve got a matrix of viewports × browsers × themes.

We also added browser and device icons to the filter dropdowns, gave the settings page a proper two-column layout, and added a banner for bulk accept-all functionality.

Delete Unwanted Screenshots

This one’s small but important. Previously, if you captured a screenshot you didn’t mean to — wrong name, test you were experimenting with, whatever — you couldn’t remove it from the TDD report. The Accept and Delete buttons just… weren’t there for new screenshots.

Now they are. Hit Delete and it removes the comparison from the report and cleans up all the associated files (baseline, current, diff). Simple, but I was surprised how often I wanted this and it wasn’t there.

Smart Variant Tree Hierarchy

When you’re testing across multiple viewports, browsers, or custom properties, the screenshot table can get overwhelming. Fifty screenshots that are really just ten screens across five viewports.

The new tree hierarchy groups variants automatically. Click the parent row to expand all its variants. Collapse it to focus on other screens. Each parent shows a variant count badge so you know what you’re dealing with.

Works across viewport, browser, device, and any custom signature properties you’ve defined. The table stays scannable even with hundreds of screenshots.

Mobile-First Fullscreen Review

Visual testing shouldn’t require being at your desk. We rebuilt the fullscreen review UI with a mobile-first approach.

On small screens, you get a collapsible menu system (more screenshot real estate), bottom sheet for comments, and touch-friendly approval/rejection buttons. On desktop, we improved navigation between screenshots and added clearer change descriptions.

It’s the same review workflow, just optimized for whatever device you’re on.

Open Source Licenses Page

Transparency matters. We added a /licenses page that lists all 41 production dependencies with their licenses. Color-coded badges for MIT, Apache, BSD, and others. Links to each package’s repository. Searchable table.

The cool part: it’s auto-generated at build time via a Vite plugin that runs license-checker and outputs JSON. Always accurate, zero maintenance.

It’s linked from the footer under Legal. If you care about what’s in your dependency tree, now you can see exactly what Vizzly depends on.

The State Machine Under the Hood

I glossed over this earlier, but the state machine migration is worth calling out. We formalized the entire build approval lifecycle:

idle → evaluating → pending_review/approved/rejected

Every state transition is explicit and testable. The state machine handles:

  • Automatic approval when all comparisons are identical
  • Cascade approval when a build is manually approved
  • Hot spot and dynamic content auto-approval
  • Review blocking and unblocking
  • Unapprove/unreject flows

Previously this logic was scattered across multiple files. Now it’s consolidated with comprehensive tests. Way easier to reason about, way easier to extend.

The state machine snapshot persists to PostgreSQL for crash recovery. If the server restarts mid-processing, the build picks up exactly where it left off.

Bug Fixes and Polish

A few things that don’t deserve their own section but made a real difference:

Baseline filename fix: There was a bug where accepting baselines would save them with double .png extensions (name_hash.png.png). This caused accepted baselines to never match on subsequent runs. Fixed.

HTTP keep-alive fix: The Node process wasn’t exiting promptly after TDD tests completed because fetch connections were staying alive. Rewrote the screenshot client to use node:http directly with keep-alive disabled.

Accessibility lint rule: We added an ESLint rule that catches navigation buttons (buttons that just do navigate()) and requires them to be proper anchor elements. Then fixed all the violations across the codebase.

What’s Next

We’re still rolling out the shared BearDen-style token language across the surfaces that need it. The goal is to keep the current product story coherent, not to keep old design-system labels alive forever.

Hot spot regions are just the beginning of smarter auto-approval. We’re looking at MS-SSIM and GMSD as additional perceptual metrics, and there’s interesting work to do around learning approval patterns over time.

And honestly? I want to keep polishing the CLI. The TUI toolkit opens up possibilities for better progress reporting, interactive workflows, and more informative error messages. The terminal is an interface too, and it deserves the same design attention as the web UI.

The Bottom Line

December was about making Vizzly smarter. Hot spot regions mean less manual approval for dynamic content. State machines mean more predictable behavior and better audit trails. The CLI and TDD dashboard got the polish they deserved.

Visual testing should feel integrated into your development process, not bolted on afterward. Every one of these updates moves closer to that goal.

Back to building.


Want to try these updates? Sign up for Vizzly and run vizzly tdd to experience the local visual development workflow. Check out the changelog for the full list of recent updates.

Ready to improve your visual workflow?

Start using Vizzly today and bring visual regression testing into the workflow described in this article.