Eight live demos · zero dependencies

Interfaces that move when you do

A single page of hand-written canvas, WebGL and SVG. Flocking birds, a pathfinder you can build walls for, a raymarched surface on the GPU — every pixel produced by code in this repository, with no framework and no build step underneath it.

01 — the demos

Everything here is running, not recorded

Each card is a self-contained ES module that starts only when it scrolls into view and pauses the moment it leaves. Drag, draw, and pull the sliders — the simulations respond in real time.

Pathfinding, three ways

A* · Dijkstra · Greedy

Drag on the grid to draw walls, or drag the two endpoints. Switch the heuristic and watch the search change shape: A* leans toward the goal, Dijkstra floods evenly, greedy sprints and sometimes takes the long way round.

drag to draw walls

Flocking

emergence

Separation, alignment, cohesion. No bird knows about the flock — each only looks at its neighbours. Hover to scatter them, hold the button down to gather them.

Flow field

generative

Particles walking a Perlin-style noise field, leaving ink behind. Every reseed is a drawing that has never existed before — and you can take one home as a PNG.

Sorting, step by step

generators

Each algorithm is a JavaScript generator that yields after every comparison, so what you see is the algorithm running — not a replay of one.

Game of Life

cellular automata

Four rules on a wrap-around grid. Cells are tinted by age, so gliders and still lifes separate visibly from the churn. Pick a stamp and click to place it.

Raymarched surface

WebGL · GLSL

One triangle, one fragment shader. Every pixel walks a ray through a signed-distance field until it hits a torus melted together with three orbiting blobs. Move the pointer to orbit the camera.

90 march steps per pixel

Live telemetry

hand-rolled SVG

A streaming chart with no charting library: the smoothing is Catmull-Rom converted to cubic Béziers, the gradients, crosshair and tooltip are all built from path data. Hover to inspect any sample.

simulated data, 10 samples/sec
02 — how it's built

Small pieces, plainly written

Every demo shares one 200-line runtime that handles the boring parts: device-pixel ratios, resize observers, pointer events, and a frame loop that refuses to run while a canvas is off screen.

0
live demos
0
dependencies
0
build steps
0
target frame rate

Loops that pay for themselves

A page with eight simulations would melt a laptop if they all ran at once. Each loop is gated by an IntersectionObserver, so only what you can actually see is burning frames — and the module itself isn't even downloaded until its card is close.

// core.js — animation, only while visible
export function loop(el, step) {
  const io = new IntersectionObserver(
    ([e]) => (e.isIntersecting ? start() : stop()),
    { rootMargin: '120px' }
  );
  io.observe(el);
}

Algorithms as generators

The sorting demo doesn't record an animation and play it back. Each sort is written the way you'd write it normally, then yields after every comparison — the renderer just pulls frames out of it.

function* quick(lo, hi) {
  const pivot = arr[hi];
  let i = lo;
  for (let j = lo; j < hi; j++) {
    if (cmp(arr[j], pivot) < 0) swap(i++, j);
    yield;            // ← one frame
  }
  yield* quick(lo, i - 1);
}
03 — about

Built with Claude Code

This page — the layout, the runtime, the eight simulations and the shader — was written in a single session with Claude Code. Clone it, open index.html through any local server, and everything runs.

Run it locally

The demos are ES modules, so they need to be served over HTTP rather than opened as a file:// path. Any static server will do:

git clone https://github.com/watsonstevenc/interactive-showcase.git
cd interactive-showcase
python -m http.server 8000   # then open http://localhost:8000

Tested in current Chrome, Edge, Firefox and Safari. The shader falls back to a short message where WebGL is unavailable, and every animation respects prefers-reduced-motion.