Create animated presentations directly on an infinite tldraw canvas.
Save camera views as slides, sequence animations for individual shapes, combine click-based and timed playback, and export the complete presentation as a portable, validated JSON document.
Built on the tldraw SDK.
Demonstration placeholder
Insert an animated GIF or short video here showing slide creation from the viewport, a per-shape animation step, and presentation playback. Do not commit a fabricated image.
- Slides from the viewport — frame any part of the canvas and save it as a slide; reorder, rename, duplicate (animations included), and delete slides.
- Per-shape animation steps — appear/disappear, fade in/out, move, scale, rotate, highlight, camera pan/zoom, waits, and parallel/sequential groups.
- Click and timer triggers — mix presenter-driven and automatic steps in one slide.
- Presentation mode — fullscreen, camera transitions, black/white screens, slide overview, keyboard + mouse navigation, speaker-note storage.
- Safe playback — animations never touch undo history; original shape state is snapshotted and restored on rewind, replay, and exit.
- Persistent & portable — auto-saves locally; exports/imports a single validated, versioned JSON file that other tools (or AI agents) can generate.
npm install
npm run dev # http://localhost:5173Other commands:
npm run test # unit tests (Vitest)
npm run test:e2e # end-to-end tests (Playwright; npx playwright install chromium once)
npm run build # type-check + production build
npm run lint # ESLint
npm run format # PrettierOn first launch the app seeds the Welcome tour, a three-slide example demonstrating fades, movement, parallel + timed steps, camera zooms, and highlights — press ▶ Present and click through it.
Two more examples are available from the Load example… menu in the top bar (they replace the current canvas after confirmation):
- Animation showcase — every primitive on its own slide: fades and visibility, move/scale/rotate plus a chained sequence, waits + staggered parallel groups + timers, and camera pans/zooms.
- Rocket launch — a story deck driven by timer chains: an automatic countdown, lift-off with parallel motion, a staggered starfield, and a camera trip to the moon.
- Draw shapes with the normal tldraw tools.
- Pan/zoom the canvas to frame a slide, then click + Slide from view. Use ⌖ Set camera to re-save a selected slide's framing.
- Select shapes on the canvas, pick an action type in the right panel, and click + Action. Actions land in the selected step (or a new step).
- In the Properties panel, set the step trigger (click or timer + delay) and the action's duration/delay/easing/parameters.
- Use ▶ on a step to preview it; shapes are restored afterwards.
- ▶ Present starts from the selected slide.
| Input | Action |
|---|---|
| Click / Space / Enter / → / ↓ / PageDown | Next step (or next slide when complete) |
| ← / ↑ / Backspace / PageUp | Previous step / previous slide |
| Escape | Exit presentation mode |
| Home / End | First / last slide |
| B | Toggle black screen |
| W | Toggle white screen |
| G | Slide overview (click a slide to jump) |
| R | Replay current slide |
Advancing during an animation finishes it immediately (no input queue). Clicking during a pending timer fires that step early. Keystrokes are ignored while typing in an input field. "Click advances" can be turned off in the top bar.
Export downloads one JSON file containing the presentation definition and
the tldraw document snapshot. Import validates the file (zod), migrates
older formatVersions, rejects newer ones, and replaces the current canvas +
slides.
The format uses stable ids and explicit discriminated-union actions so it can be generated programmatically — see docs/presentation-schema.md.
The playback engine (src/presentation/engine.ts) is plain TypeScript with no
React or tldraw imports; it talks to the canvas through a small port interface
adapted to tldraw in src/presentation/tldrawPort.ts, and all mutations bypass
undo history. See docs/architecture.md and
docs/animation-engine.md; research notes on the
tldraw SDK and prior art are in docs/research.md.
src/
animations/ tween/delay engine + easings
components/ shared UI (error boundary)
editor/ editor-mode panels
presentation/ engine, action runner, controller, overlay, ports
schemas/ data model, zod validation, migrations
state/ Zustand stores + pure document operations
storage/ JSON export/import, example seed
utils/ ids, camera math, labels
tests/
unit/ Vitest (engine, animator, operations, serialization)
e2e/ Playwright (editing + presentation flows)
- Slide thumbnails are name-only (no canvas previews in the navigator or overview).
- Parallel/sequence groups are fully supported by the engine and JSON format, but the editor UI only creates flat groups ("Run together"); nested groups must be authored in JSON.
- Speaker notes are stored and editable but there is no separate presenter view.
prefers-reduced-motionis not respected yet.- Highlight color changes apply only to shapes with a tldraw
colorstyle (geo, draw, text, note, arrow). - Single local document; no multi-presentation library, collaboration, or cloud storage (deliberately out of scope for v1).
- Slide thumbnails and an on-canvas "show slide bounds" overlay.
- Presenter view (notes + next step) in a second window.
- Nested group editing and a drag-and-drop timeline.
- Reduced-motion support via tldraw's animation-speed preference.
- Path-based motion (move along a drawn curve).
- AI generation endpoint: feed the JSON schema to a model and import the result directly.
MIT