Skip to content

cadamsmith/algo-viz

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

6 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

algo-viz

Interactive visualizations of non-trivial algorithms, built to demonstrate computational geometry, graph theory, and optimization knowledge. Each algorithm is implemented from scratch in Go, compiled to WebAssembly, and rendered via the Canvas API with no visualization libraries.

Purpose

Emphasis on correctness, clean architecture, and visual clarity. All algorithm logic is written in pure Go β€” no JS, no external dependencies on the logic layer.

Tech Stack

  • Go β€” all algorithm logic and WASM binaries
  • WebAssembly β€” Go compiled to .wasm, loaded in the browser
  • Vite β€” build tool and dev server for the JS shell
  • TypeScript β€” thin JS shell for bootstrapping WASM and wiring the UI
  • Canvas API β€” all rendering (no D3, no charting libraries)
  • Tailwind CSS β€” styling
  • go test β€” unit testing for all algorithm logic

Project Structure

algo-viz/
β”œβ”€β”€ go/                          # all Go source
β”‚   β”œβ”€β”€ algorithms/              # pure algorithm logic β€” no syscall/js, no side effects
β”‚   β”‚   β”œβ”€β”€ voronoi/             # Fortune's Algorithm
β”‚   β”‚   β”œβ”€β”€ edmonds_karp/        # Maximum Flow
β”‚   β”‚   β”œβ”€β”€ simulated_annealing/ # Simulated Annealing for TSP
β”‚   β”‚   β”œβ”€β”€ kd_tree/             # KD-Tree + nearest neighbor
β”‚   β”‚   └── aho_corasick/        # Aho-Corasick string matching
β”‚   β”œβ”€β”€ wasm/                    # WASM entry points, one per algorithm
β”‚   β”‚   β”œβ”€β”€ voronoi/main.go      # exposes JS-callable functions via syscall/js
β”‚   β”‚   β”œβ”€β”€ edmonds_karp/main.go
β”‚   β”‚   β”œβ”€β”€ simulated_annealing/main.go
β”‚   β”‚   β”œβ”€β”€ kd_tree/main.go
β”‚   β”‚   └── aho_corasick/main.go
β”‚   └── go.mod
β”œβ”€β”€ src/                         # TypeScript shell
β”‚   β”œβ”€β”€ wasm/                    # WASM loader + JS bindings per algorithm
β”‚   β”‚   β”œβ”€β”€ loader.ts            # shared WASM instantiation helper
β”‚   β”‚   β”œβ”€β”€ voronoi.ts
β”‚   β”‚   β”œβ”€β”€ edmondsKarp.ts
β”‚   β”‚   β”œβ”€β”€ simulatedAnnealing.ts
β”‚   β”‚   β”œβ”€β”€ kdTree.ts
β”‚   β”‚   └── ahoCorasick.ts
β”‚   β”œβ”€β”€ visualizers/             # canvas rendering, one file per algorithm
β”‚   β”‚   β”œβ”€β”€ VoronoiVisualizer.ts
β”‚   β”‚   β”œβ”€β”€ EdmondsKarpVisualizer.ts
β”‚   β”‚   β”œβ”€β”€ SimulatedAnnealingVisualizer.ts
β”‚   β”‚   β”œβ”€β”€ KdTreeVisualizer.ts
β”‚   β”‚   └── AhoCorasickVisualizer.ts
β”‚   β”œβ”€β”€ components/              # shared UI
β”‚   β”‚   β”œβ”€β”€ AlgoCanvas.ts        # canvas wrapper with resize handling
β”‚   β”‚   β”œβ”€β”€ Controls.ts          # play/pause, speed, step, reset
β”‚   β”‚   β”œβ”€β”€ InfoPanel.ts         # algorithm description + complexity
β”‚   β”‚   └── Nav.ts               # navigation between visualizers
β”‚   β”œβ”€β”€ pages/                   # one entry point per algorithm
β”‚   β”‚   β”œβ”€β”€ voronoi.ts
β”‚   β”‚   β”œβ”€β”€ edmondsKarp.ts
β”‚   β”‚   β”œβ”€β”€ simulatedAnnealing.ts
β”‚   β”‚   β”œβ”€β”€ kdTree.ts
β”‚   β”‚   └── ahoCorasick.ts
β”‚   └── hooks/
β”‚       β”œβ”€β”€ animationLoop.ts     # rAF loop abstraction
β”‚       └── canvasResize.ts      # ResizeObserver canvas scaling
β”œβ”€β”€ public/
β”‚   β”œβ”€β”€ wasm/                    # compiled .wasm binaries (build output)
β”‚   └── wasm_exec.js             # Go's WASM runtime shim (copy from GOROOT)
β”œβ”€β”€ dist/                        # Vite build output
β”œβ”€β”€ README.md
β”œβ”€β”€ index.html
β”œβ”€β”€ vite.config.ts
β”œβ”€β”€ tailwind.config.ts
β”œβ”€β”€ tsconfig.json
└── build.sh                     # compiles all Go packages to WASM, then runs Vite

Architecture Rules

Go owns all logic. Files in go/algorithms/ must be pure Go β€” no syscall/js, no global state, no I/O. They receive input and return output. This makes them independently testable with go test and portable outside the browser.

WASM entry points are thin wrappers. Files in go/wasm/ import from go/algorithms/ and expose functions to JavaScript via syscall/js. They should contain no algorithm logic β€” only marshalling and JS bindings.

TypeScript is a shell, not a framework. The src/ layer loads WASM, wires up the canvas, and handles UI state. It does not reimplement any algorithm logic. Keep it minimal.

Visualizers own the canvas. Visualizer files receive a CanvasRenderingContext2D and algorithm state returned from WASM, and draw. They do not own animation timing β€” that belongs to animationLoop.ts.

Algorithms

Algorithm Category Key Concepts
Fortune's Algorithm Computational Geometry Sweep line, beach line, parabolas, half-edge DCEL
Edmonds-Karp Graph / Network Flow BFS augmenting paths, residual graph, max-flow min-cut
Simulated Annealing (TSP) Optimization Probabilistic hill climbing, cooling schedule, combinatorial search
KD-Tree Spatial Data Structures Binary space partitioning, nearest neighbor, range search
Aho-Corasick String Algorithms Trie, failure links, finite automaton, multi-pattern matching

Controls (shared across all visualizers)

Every visualizer must support:

  • Play / Pause β€” start and freeze the animation at any point
  • Step β€” advance exactly one logical step when paused
  • Speed slider β€” control animation playback rate
  • Reset β€” restore to initial state
  • Randomize β€” generate new input (where applicable)

Code Style

Go

  • gofmt enforced β€” no exceptions
  • Every exported function must have a doc comment
  • Algorithm files must have a package-level comment explaining the algorithm, time complexity, and space complexity
  • No interface{} / any in algorithm logic β€” use concrete types

TypeScript

  • Strict mode enabled β€” no any, no type assertions unless unavoidable
  • Keep the shell lean β€” if logic is creeping into TS, it belongs in Go

Testing

All algorithm logic in go/algorithms/ must have _test.go files. At minimum, test:

  • Correctness on known inputs
  • Edge cases (empty input, single point, degenerate cases)
cd go && go test ./...

Dev Commands

# compile all Go packages to WASM and copy to public/wasm/
./build.sh

# start Vite dev server (run build.sh first)
npm run dev

# production build
npm run build

# run Go tests
cd go && go test ./...

Building WASM

Each Go package in go/wasm/ is compiled separately:

GOOS=js GOARCH=wasm go build -o public/wasm/voronoi.wasm ./go/wasm/voronoi/

build.sh handles this for all five algorithms. wasm_exec.js must be copied from your local Go installation:

cp "$(go env GOROOT)/misc/wasm/wasm_exec.js" public/

Deployment

Deployed to Cloudflare via the unified Workers + Static Assets flow (the successor to classic Pages). Connects directly to the GitHub repo β€” pushes to main trigger automatic builds and deploys. Live demo link is pinned in the repo description.

Build settings in the Cloudflare dashboard:

  • Build command: ./build.sh && npm run build
  • Deploy command: npx wrangler deploy

Asset config lives in wrangler.toml ([assets] directory = "./dist"). Hash routing keeps every URL on /, so no SPA fallback is needed.

Note: Cloudflare's build image includes Go β€” no custom Docker image needed.

About

🧠 (WIP) Go + WASM algorithm visualizations

Resources

License

Stars

Watchers

Forks

Contributors