Willi Krappen

Drone Show Designer

Work in progress

Browser-based, node-based editor for aerial drone light shows: a graph model as single source of truth, live 3D viewport, deterministic bake pipeline, AI agent with 30+ tools operating directly on the graph. Work in progress — live and functional, still under active development.

Drone Show Designer

Key engineering call

The ShowGraph is the single canonical state — the React Flow canvas, Three.js viewport, inspectors, validator and exporter are all derived views. No duplicated state, no drift. Cost: live preview is allowed to approximate, bake is not — the split is explicit and tested.

Most drone-show tooling is Blender plugins or proprietary desktops. This is a from-scratch, web-native editor: a typed ShowGraph (launch → formation → transition → idle → land) is the canonical state; the React Flow canvas, Three.js viewport, inspectors, validator and exporter are all derived views. A Claude tool-calling agent writes directly to the graph, with a history snapshot before every write so Ctrl+Z undoes any AI change. A standalone companion takes a text prompt and produces formation JSON plus a Blender import script.

Actively developed. The live deployment at drones.prototyp.ms is running and the core (graph engine, preview, bake, AI agent) is solid — but new tools, music-sync and polish keep landing.

Architectural laws

Four rules enforced in code (and in tests). They keep the editor extensible without softening the core.

  1. 1

    ShowGraph is canonical. Everything else is a derived view.

  2. 2

    Live preview is allowed to approximate; bake is not.

  3. 3

    Transitions own point mapping, entry/exit and motion interpolation — never timing or drone allocation.

  4. 4

    Registries are the only extension surface. Adding a transition, generator or color program is a single register…() call.

What's in the editor

The libraries behind the nodes. Everything registrable, everything reachable by the AI agent.

Formation generators

ring · grid · sphere · spiral · line · heart · star

7 procedural generators — parameter-driven, editable straight from the inspector.

firework-burst · apple-tree-shake · breathing-sphere

3 animated formations with their own internal timing.

create_formation_from_text

Free text to point cloud — generated by the AI agent straight into the graph.

Transition strategies

stagger · spiral · explosion · implosion · cascade · morph · color-sweep · bounce

8 strategies. Each owns its own point mapping and minimum-duration estimator — but not timing or drone allocation (see architectural law no. 3).

Idle behaviors

hover · orbit · breathe · random-walk · figure-8 · swarm · sparkle · pulse · wave · spin · drift

11 idle behaviors for drones attached to formation nodes — with per-axis inheritance flags.

Color programs

solid · gradient · rainbow · pulse · chase (10 Programme)

10 color programs — solids, gradients, rainbows, pulses, chase patterns.

Key engineering decisions

Graph as single source of truth

One typed model — launch / formation / transition / idle / land plus flow and attachment edges — is the canonical state. The React Flow canvas, Three.js viewport, inspector panels, validator and exporter are all derived views. No duplicated state, no drift.

Preview vs. bake — two clear paths

evaluateAtTime() runs on the main thread, sub-16ms per frame for 60 fps scrubbing, with deliberate approximations. bakeShow() runs in a Web Worker with full physics enforcement and is the only thing allowed to produce export trajectories. The contract between the two is explicit and tested.

AI agent as a first-class editor

A Claude tool-calling agent has access to 30+ typed tools — create_formation_from_text, add_transition_node, set_color_program, generate_music_synced_show, analyze_image_for_formation, fix_all_violations. Every write tool snapshots history first, so any AI change is undoable with Ctrl+Z.

Registries as the only extension surface

A new transition, a formation generator, a color program — one register…() call. That keeps the system equally extensible by me and by AI tooling — the engine only knows about strategies, not their specific implementations.

Physics validation separated from the editor

Per-segment velocity (horizontal + vertical), acceleration, drone-pair spacing, altitude floor and geofence are validated against the baked result. Auto-fix patches exist for the common violations; auto-timing assigns durations to satisfy constraints.

Crash recovery via IndexedDB

Autosave lands in IndexedDB. After a reload-following-crash, the editor offers to restore the most recent in-progress show — no lost state from a browser crash or accidental tab close.

Project shape (as of now)

Stats from the current state. Test LOC isn't counted as 'size', but it's relevant for the quality of the hard parts.

MetricValue
Source files (excl. tests)110
Source LOC (excl. tests)~22,700
Test files41
Test LOC~7,900
Registered AI tools30+
Transition strategies8
Idle behaviors11
Formation generators7 + 3 animated

Status — what stands, what's in flight

What stands

stable

Graph engine, preview path, deterministic bake in a worker, 8 transitions / 11 idles / 10 color programs, IndexedDB autosave, CSV export. 41 test files cover the hard parts — topology, timing, round-trip serialization, split/merge flow.

What's in flight

in progress

AI agent is live but new tools keep landing; the music-sync pipeline is still expanding; the MP4 render export is optional and not production-grade yet. The standalone companion is its own small app slot, not yet fully wedded to the main editor.

What is intentionally out

non-goals

Multi-user collaboration, cloud storage, a proprietary hardware protocol. The editor is single-user, browser-first, and exports to open formats (CSV waypoints + JSON project). That is staying that way.

Deployment

Static Vite build served by nginx on the same VPS as my other .prototyp.ms apps. No server component: every AI call runs with a user-supplied Claude API key directly from the browser. Without a key the editor works fully — only the chat panel is disabled.