Component 2 of 3 · the picture

The graph, drawn.

A single-page Svelte app: force-directed graph, scope trees, filters, quality report, commit diff. It holds no analysis logic of its own — it asks the engine seven questions over HTTP and draws the answers. Which is what makes it portable: the same build runs in a browser tab, inside the VS Code webview, and on a static host with no engine at all.

The one thing to understand

It needs an API, not a process.

This is the distinction that decides where the visualizer can go. The UI never opens a JSON file and never shells out — it calls the endpoints below. A running binary answers them from a live analysis; a directory of files answers them just as well, because not one of them takes a query parameter.

Live

mezz watch . / mezz serve

Data
Your source, re-analyzed on save
Can do
Everything: scope changes re-analyze, diff reads git worktrees, the context panel opens files off disk.
Where
Your machine.

Frozen

Any static file host

Data
API responses baked ahead of time
Can do
Read-only: browse, filter, rank, inspect. Anything that would re-run the analyzer answers 403.
Where
This site — /visualizer is exactly this.
the entire read surface
GET /api/hello                    # who is answering
GET /api/repos                    # which repos exist
GET /api/repos/{slug}             # metadata
GET /api/repos/{slug}/graph       # entities + relationships
GET /api/repos/{slug}/index       # names, for search
GET /api/repos/{slug}/details     # metrics, smells
GET /api/repos/{slug}/commits     # history, for the diff picker

Six routes, all keyed by a slug. That finiteness is the whole trick — bake each response once and the app runs with nothing behind it, which is exactly what the page you are on does.

Not a demo build

The actual tool, running here.

Everything on /demo is a small viewer written for this site. This is the opposite: the real UI out of the Mezzanine repository, frozen mode, against public repositories it analyzed once. There is no second copy to keep in sync — rebuild Mezzanine and this moves with it.

Mezzanine UI · … repositories · frozen open full screen ↗

It opens where the real tool opens: on the scope picker. Tick a folder — or take the suggestion it makes — and the graph renders. Scopes past ~2,000 entities are marked and held back rather than dropped on you, which is why the big repositories below want a narrower pick.

The interaction worth knowing

Search narrows the picture without deleting it.

Typing previews; committing filters. Type a query and you get a results list and nothing else — the graph is untouched. Enter, or a per-row checkbox, commits matches into the drawing.

  • Shift-click commits a run. Click a row, shift-click a later one, and the whole range commits in two clicks rather than one per row. Editing the query resets the anchor.
  • Non-matches dim rather than vanish. A committed search used to delete everything around what it found, which threw away the context that made the match legible. They now fade to 15% and stay on the canvas; one-hop neighbours stay at full opacity. Hide non-matches restores the old behaviour when you want the empty stage.

And in the corner

The bundle names itself.

A build stamp reports the commit the UI was built from, and the commit of the engine answering it. It exists because a UI can be served from several places — a checkout, a copy beside the installed binary, a bake like this one — and a stale copy shadowing a rebuild otherwise looks exactly like a rebuild that did nothing.

Above, it reads engine —, which is the honest answer: there is no engine, only files. Run the binary and the second half fills in, and disagrees with the first when one of the two is behind.

What you're driving

Three blocks, ordered by what a change costs.

In the editor these sit in the activity bar and follow your cursor. Here they run in a browser tab against a frozen analysis. The code is identical — one Svelte app, three hosts.

The sidebar used to be nine controls in a flat list, which hid the thing that matters most about them: a checkbox in the first block re-runs the analyzer, and one in the third just stops drawing a node. Each block now says which.

1Analysis

Re-runs analysis or refetches.

Root Path
Which checkout is being read. Local mode only.
Parsed Languages
Which languages the analyzer reads at all. Apply re-parses the repo.
Analysis Scope
Which code loads into the canvas — the most consequential control here.

2Graph Visualization

Redraws from data already loaded.

Files
Hide files from the picture without changing what is analysed.
Languages
Narrow the drawing by source language.
View Options
Entity / class / module aggregation, depth, density, labels.

3Post-Filtering

Narrows or emphasises what is drawn. Reloads nothing.

Entities
Search, and the entity-kind toggles that go with it.
Relationships
Which edge kinds are drawn.
Level Filters
Depth and neighbourhood around the selection.

What frozen mode costs

Read-only, on purpose.

  • No repo submissions. mezz serve can clone and analyze a GitHub repo on request; that is unbounded work on someone else's machine, so the site's proxy refuses it. The hosted set is fixed.
  • No live reload. The event stream exists to report analysis progress. With submissions off it has nothing to say, so it is switched off too.
  • No diff overlay. Comparing two commits means git worktrees on the server. That one runs locally, in the extension.
  • No source panel. Reading the file behind an entity means reading it off disk. Locally that is your disk; here there is none.

Every one of those is present the moment you run the binary yourself — which is the point of the tool being local. Nothing is a paid tier; it is just the difference between a process and a CDN.