A proper scroll-timeline editor for the Animation Engine — reuse Kinetic Scenes, or build one?
The question: The Animation Engine's weakest point is authoring. You set scroll motion per element through option sliders, with no way to see or coordinate how a whole page choreographs as you scroll. We want a proper visual tracks-and-keyframes timeline. Do we build one inside the page builder, or reuse the Kinetic Scenes timeline — the fixed-viewport, time-based editor we already ship — driven by scroll instead of a clock?
Context
Two things we already own change the calculus:
- Kinetic Scenes is a working timeline editor + player for fixed-viewport scenes. A full visual timeline editor built from scratch inside a builder is "a product unto itself" — but we have that product.
- A pinned Section supplies the two things Kinetic Scenes needs: a fixed stage (pin it and the viewport freezes for a known slice of scroll) and a playhead (that scroll distance). So a "scroll scene" is just Kinetic Scenes with the playhead swapped from a clock to scroll progress.
The only open question was whether the Kinetic Scenes code is actually coupled to its time clock, or can be driven by an external scroll progress — i.e. reuse vs. rebuild.
The probe (2026-10-21)
Read the Kinetic Scenes packages/player and apps/studio directly:
- Player — not coupled to a clock. It compiles the whole scene into one seekable GSAP timeline
and exposes
tl.progress(p)/tl.time(t). It already ships ascroll.tsmodule (linkToScroll({ … setProgress })) that drivestl.progress(p)from scroll position — with a pinned sticky stage forlengthwindow-heights, a sticky-headeroffsetparameter, and smoothing. It plays a portable Scene JSON viamount(host, scene, opts). Scroll-scrubbing is a first-class, shipping mode; the clock (play()/pause()) and scroll are two drivers of the same seekable timeline. - Editor — a clean reusable component.
Timeline.tsx(~692 lines) +KeyframeEditor.tsxare props-driven and store-agnostic (no zustand/context) — they take aScenein and emit aSceneout via callbacks. They are bound to the Scene format and the studio'slib/*ops (sceneOps, keyframes, markers, cameraOps), not to the app shell.
Options considered
- A — Scene-native. Store a Scene JSON per pinned "Scroll Scene"; reuse player + editor as-is. Fastest and maximum reuse — but the scene becomes a parallel format alongside native builder options, a second place a site's motion lives.
- B — Compile native ⇄ Scene (chosen). The builder stores native options; a thin compiler maps them to a Scene the player scrubs and the reused editor edits. Native data model preserved; reuse both runtime and editor. Cost: one bidirectional mapping layer to build and keep in sync.
- C — Rebuild the editor natively, reuse only the player. Most control, least reuse, biggest build — and wasteful, since the Timeline component is already reusable.
Decision
Reuse Kinetic Scenes — both the player and the Timeline/keyframe editor — bridged by a native-options ⇄ scene compiler (option B). The scene is a compile target / view, never a file stored on the site. The Animation Engine stays the home of the data (native builder options + the Advanced box); the compiler produces a scene on the fly for the player to scrub and the editor to edit.
Why
- The player already does scroll (pin + offset + smoothing, seekable timeline). Rebuilding a scroll runtime (C) would duplicate shipping code; being coupled to a clock (the risk that justified a probe) turned out to be false.
- The Timeline editor is a clean, reusable component, so a from-scratch builder timeline (C) is wasted effort.
- Keeping the data model native (the roadmap's stated goal) rules out A's parallel Scene file — the compiler keeps the scene ephemeral, so there is no second home for a site's motion and nothing to drift out of sync in the database.
- The remaining cost is one well-scoped mapping layer, far smaller than building either a scroll runtime or a timeline UI from scratch.
This is Phase 1b of the Animation Engine 3D Motion & Roadmap. Status: Accepted.
