Myers Visualizer
An interactive replay of what git diff does inside, including why it sometimes blames the wrong line

- diff algorithms written from the paper
- 4
- on a 300×300 edit graph
- 59.9 fps
- search steps in the worst case, no freeze
- 135,152
- presets, each showing one diff behaviour
- 8
On this page
The problem
Developers run git diff almost every working day, and very few know what it does. A diff shows up only as its result. Nothing in that result hints that it came from a shortest-path search over a grid.
The confusing parts go unexplained too. Everyone has seen a diff blame a closing brace on the wrong function, or show "insert 2 lines" as "delete 5, add 7". People treat that as a quirk. The real reason is that the shortest set of edits is usually not unique, and the algorithm's tie-breaking picks one without any sense of what reads well. That is also why git ships other diff algorithms, such as patience.
I built Myers Visualizer for working developers, for students and teachers of graph search, and for anyone reading Eugene Myers' 1986 paper who wants the diagrams to move.
What I built
I wrote the diff engine from the paper
I implemented four diff algorithms myself: greedy Myers, the memory-saving linear-space Myers, patience and histogram. There is no diff library in the project. The engine takes two texts and options and returns the edits, a full recording of the search, and stats. It has no clock or randomness, so the same input always gives the same output. Because the search is recorded once, stepping backwards costs nothing.
I wrote the checker before the algorithm
Before any Myers code existed, I wrote two independent checks. One applies an edit script to the first text and confirms it produces the second. The other is a slow brute-force search that finds the true minimum number of edits. Every algorithm, on every input, must pass both. The tests never expect two algorithms to give the same edits, only the same count, because several minimal answers can be correct.
The grid is drawn on canvas and the search runs off the main thread
The edit graph is the product, so a 300×300 drawing test came before any algorithm code. I draw the grid on canvas, so the page doesn't create an element per cell. Each frame only redraws the search frontier. The search itself runs in a background worker with a step budget, so even the worst-case preset can't freeze the page.
Every preset's claim is tested
Two of my first preset claims turned out to be false when I checked them. My tie-breaking did not blame the wrong brace on the first input I tried. I replaced both with inputs that do show the effect, and now each of the 8 presets asserts its claim in a test. That rule is written into the repo's working instructions.
I rebuilt the site for someone who has never run git diff
Late in the build I reordered the home page around a newcomer. It opens with a question, then a worked example without jargon, the idea in three steps, and why diffs blame the wrong line. Notation and the glossary come last. The grid also gained axis labels, since a newcomer who guesses them wrong reads the whole picture backwards.
Result
Myers Visualizer is live, public and open source. It installs as an app and works offline after the first visit. It shows the edit graph as it fills, the algorithm's working memory beside it, how many equally minimal answers exist, and a side-by-side of all four algorithms. In the site's own example, all four need 5 edits and patience still halves the number of changed blocks.
It runs at 59.9 frames per second on a 300×300 grid. At the input cap, the worst case takes 135,152 search steps and the page stays responsive. It comes in English and Indonesian. I built it in two days in August 2026.
Under the hoodTechnical detail for engineers
- The engine is a pure function,
(a, b, options) → { script, trace, stats }, with no React, DOM, clock, randomness or module-level state. Text is tokenized into integer ids first, so line vs. character granularity and whitespace handling are explicit settings. lib/diff/(~1,750 lines) holds greedy Myers withVrecording and backtrack, the linear-space bidirectional variant with the middle snake, patience and histogram. No diff library.apply.ts(script + A → B) shares no code with any search;brute.tsis a BFS over the edit graph for the true minimalD. Both were written beforemyers.ts. Tests assertDequality and apply-correctness, never script equality.- The
Varray is indexed byk = x − y, which goes negative. The offset sits behind one named accessor and is never inlined, since an off-by-one there looks plausible on symmetric input. - Canvas 2D rendering, hand-written. Per-frame work is O(frontier), not O(N·M), guarded by a unit test.
pnpm bench:renderbuilds, serves under the production basePath and drives headless Chrome: 220 frames, draw mean 0.13 ms, p95 0.30 ms, frame median 16.70 ms (59.9 fps). Kept out of CI because timings on shared runners flake.- jsdom has no
Workerand a stub canvas, so a Puppeteer smoke test reads pixels back from the built export and confirms the worker chunk loads. It immediately found a bug: the URL hash was only read on mount. The live URL passes the smoke suite 15/15. - Worst case at the input cap:
D = 600, 135,152 search steps, 362,404Vcells. Linear-space mode shows a live memory counter for O(D²) vs O(N+M). In the comparison example all four algorithms agree onD = 5. - 8 presets:
minimal-edit,pure-insert,pure-delete,transposition,brace-misattribution,patience-wins,worst-case,char-level, each asserted intests/presets/. - Static-export fixes:
app/manifest.tsignoredbasePath(silent 404, no install prompt), so the manifest is a static file pinned by a test.metadataBasealready carries the basePath, so a root-relative OG image got it twice. - The project started Indonesian-first and was renamed and re-defaulted to English. Algorithm terms stay English in both locales.
- Three runtime dependencies (Next.js 14.2, React, react-dom). 87.4 KB gzipped shared first-load JS, 107 KB on the graph page, against a 250 KB budget.
- Out of scope: file upload, directory diff, three-way merge, AST diffing, accounts. The site says git applies extra heuristics and doesn't claim byte-identical parity with git diff.
- ~8,900 lines of TypeScript, 152 tests in 24 files, 25 commits from 4 to 5 August 2026.
Screenshots
Hiring, or building something similar?
I'm open to full-time roles and select freelance work.