# The One-Person Product Team: HTML + three.js deck
Raul Popadineți · AGENTIC.TM x Indie TM · prow 2026 side event · 28 Oct 2026 · Haufe Group, Timișoara

## Start (fully offline)
    cd html && python3 -m http.server 8000      # then open http://localhost:8000
or double-click `start.command` (macOS) / run `./start.sh`.
No server at all? Double-click **deck-single.html**: everything (JS, fonts, images) is inside that one file.
Use Chrome or Edge, full screen (F). The projector can be any resolution; the deck letterboxes to 16:9.

## Keys (clicker-compatible)
| Key | Action |
|---|---|
| → ↓ Space PageDown Enter | next (on the title the steam engine spins up and flips the title letters on, about 3.3 s; press again to skip) |
| ← ↑ PageUp Backspace | previous |
| F | fullscreen |
| N | presenter window: notes, timer (click it to reset), clock, NOW and NEXT previews. It drives the deck too (BroadcastChannel plus postMessage) |
| R | replay the current slide's animation |
| B or . | black screen |
| H | key help |
The URL hash (`#5`) is the slide number, so a reload keeps your place. `?nogl` forces the plain HTML/CSS fallback.

## Structure
- `src/slides.js`: the deck as data (one registry: id, title, theme, notes, back/front DOM, enter, exit, finish)
- `src/engine.js`: one shared WebGL renderer and one cannon-es physics world; each slide gets a `Ctx` that frees its meshes, textures, bodies and timers on teardown
- `src/fx.js`: particles (fire, smoke, confetti, dust), DOM→3D extruded letters→rigid bodies, cut-out drift, robots and stamps, money pop-ups
- `deck.js`: the bundled build (rebuild with `tools/build.sh`, which also rebuilds deck-single.html)
- `tools/verify.py`: Playwright check (screenshots at 1920x1080 and 1366x768, console errors, photo ratios, QR decode from the rendered slide, leak check, keys, presenter, fallback); `tools/record_title.py`: records the title power-on to video and extracts frames
