# Kinetic for WildflowerJS: the condensed reference This file describes Kinetic 0.1.1, updated October 31, 2026. > Kinetic (`@wildflowerjs/kinetic`) is a WildflowerJS extension that turns a > web page into a video. This file is the condensed, single-fetch reference > for code generation. The framework it extends has its own at > https://www.wildflowerjs.com/llms.txt, and the full Kinetic corpus (every > documentation page with every example) is at > https://kinetic.wildflowerjs.com/llms-full.txt. > A Kinetic page is a WildflowerJS page, and every framework attribute and > API works in it: for anything about WildflowerJS itself (whether > `data-bind-html` exists, what a checkbox's `data-model` writes), read > https://www.wildflowerjs.com/llms.txt rather than guessing. > The guide written for assistants ships in the npm package: read it at > https://cdn.jsdelivr.net/npm/@wildflowerjs/kinetic@0.1/skills/wildflower-kinetic/SKILL.md, > or where only the package registry is reachable, `npm pack @wildflowerjs/kinetic` > and open package/skills/wildflower-kinetic/ in the tarball. > Beside it, references/start.md has two complete pages to start from (a > video, and an interactive lesson that is also its own video), and > references/patterns.md has working patterns, one idea at a time. ## The smallest working page `index.html`: ```html

Hello

``` `scenes.js`: ```javascript const { scene, typewriter } = wildflower.kinetic; scene('title', { keyframes: { heading: { opacity: { at: [0, 0.5], to: [0, 1] }, translateY: { at: [0, 0.8], to: [40, 0], ease: 'spring' }, }, }, computed: { line() { return typewriter(this.local - 0.6, 'A page that is also a video.', 20); }, }, }); ``` Open `index.html` in Chrome, from disk or served: it loads only scripts. `data-preview` adds the bar that plays, checks and renders it. ## Where the page will open - **As one file:** put the page's own code in `

``` Interactive mode. `$kinetic.mode` is `'interactive'` or `'video'`. `config({ mode })` is `'auto'` (the default: video with the preview bar up, interactive otherwise), `'interactive'` or `'video'`; a renderer's runtime on the page, a render capturing, `check()` and `render()` put the page in video mode whatever the setting. In video mode the clock plays straight through and each step's `script` writes its store paths on every seek; in interactive mode each step plays and holds, and the learner's controls write the same paths. A step is a clip with an `id` and `data-step` (chain them with `data-start="circle"`); its range runs to the next step's start. ```javascript wildflower.store('sine', { state: { angle: 30, choice: null }, computed: { answered() { return this.choice !== null; } } }); wildflower.kinetic.step('circle', { wait: 2, // interactive: holds 2 s into the step; default the shorter of its range and its clip; false plays on script: { 'sine.angle': { at: [2, 5.5], to: [30, 120], ease: 'power2.inOut' } }, // video: a track in the step's seconds }); wildflower.kinetic.step('ask', { wait: 1, until: 'sine.answered', // interactive: once truthy, plays the rest of the step and holds on its last frame for Next; canAdvance waits for it entry: { 'sine.choice': null }, // interactive: written as the step is entered script: { 'sine.choice': { at: [0, 2], set: [null, 270] } }, // video: settings, strings, numbers, booleans or null }); wildflower.kinetic.scene('sine-circle', { subscribe: ['sine'], follow: { angle: 'sine.angle' }, computed: { point() { return at(this.angle); } } }); wildflower.kinetic.next(); wildflower.kinetic.back(); wildflower.kinetic.go('ask'); // interactive: enter a step with its entry; video: seek to its start wildflower.kinetic.config({ mode: 'video' }); wildflower.kinetic.play({ from: 0 }); // "watch it as a video"; config({ mode: 'interactive' }) gives the learner's values back document.addEventListener('kinetic:step', (e) => { /* e.detail { step, index }: interactive mode, after the entering seek */ }); ``` The store also has `step` and `stepIndex` (the step whose range holds `time`, both modes, written in the seek's batch), `stepCount`, `stepStart`, `stepLength`, `waiting` (interactive mode, true once the hold's seek has settled) and `canAdvance`, which a Next button binds to: in interactive mode it follows the step's `until` path (true when there is none), wherever the step is; always true in video mode. `next()` enters the next step at once, wherever the step is, the rest of it unplayed, and Kinetic never moves to the next step by itself; Back always works. At a hold the clock stands still, so `local` does too, and what the learner changes moves only through `follow` springs or bindings to state: design a hold around a control and what follows it. In interactive mode `play()` plays on to the step's hold, and at or past it plays the step again. With `autoplay` on, an interactive page with steps enters its first step when readiness resolves, never when it fails. In video mode a path's value comes from the scripts alone, never from the store, so any seek order gives the same frame; a write to a scripted path by anything else is undone within a microtask (KN-146), a watcher's write inside the script's own write too, once per path between two seeks (a watcher that writes it again every time keeps its value, with KN-146 printed), so disable every control that writes a scripted path, and every quiz button, in video mode (`data-bind-attr="{ disabled: $kinetic.mode === 'video' }"`). Switching to video keeps the learner's values aside and switching back writes them back; `check()` and `render()` seek back first, still in video mode. A script path whose store does not exist, or that names a computed, fails readiness (KN-100). `follow` eases toward a store path by a spring only (`'spring'`, `{ spring: { stiffness, damping, mass } }` or `{ spring: { duration, bounce } }`, `{ duration: 0.4 }` by default; another ease and `overshootClamping` are KN-100): interactive, a sum of one step response per change on the page's clock; video, the same spring on the target's script, sampled on the root's `data-fps`. The script's writes are real store writes, so interactive-only effects go in action handlers, `entry` or the `kinetic:step` event, and a store with scripted paths has no `autoSave`. A step that explains a change is a task the learner does, with `until` waiting for it. Once `until` is truthy at the hold, interactive mode plays the rest of the step's range and holds on its last frame, waiting for Next (a hold at the range's end stays where it is), so a question holds before its explanation: `wait` earlier than the step's end, the explanation a clip after it, and a wrong answer's feedback a binding on the store shown during the hold. Hints and "try it" prompts read the mode (`data-show="$kinetic.mode === 'interactive'"`), so the video has none of them. `scripts/check.cjs --lesson` in the skill walks each step and reports its hold (the last frame before its `wait`) and its `until`. A lesson page has no renderer runtime tag, and no `data-preview` unless it calls `config({ mode: 'interactive' })`, since under `'auto'` the bar puts it in video mode (KN-158). In interactive mode on a page with steps KN-132 and KN-143 are off. KN-118 warns about a `data-step` with no `id` or `data-start`, two steps with one `id`, a step inside a step, two steps that start together and a first step after 0; KN-157 about `step()` for no element, an `until` or `follow` store missing at readiness, a `wait` past the range and a settings entry after 0 in the first step that scripts its path. Diagnostics print as `[KN-nnn]` (through `wildflower.diagnostic()` with a development build of WildflowerJS, which keeps them in `wildflower.diagnostics`). The ranges are 10x install and the seek channel, 11x the composition's markup, 12x tracks and eases, 13x inputs, readiness and audio clips, 14x determinism hazards during a seek, 15x the scene definition, 16x `check()`, 17x seek cost, 18x Lottie and animated images, 19x Trillium and 20x `render()`. KN-100, KN-120, KN-121, KN-200, KN-201, KN-203 (an audio encoder delay that cannot be measured), KN-204 (media from another origin) and KN-206 (a runtime player's frames miss the render's) throw on every build. KN-130, KN-131, KN-133, KN-135, KN-180 (a Lottie animation's `data_failed`) and KN-181 (an animated image that cannot be fetched or decoded) print a `console.error` and hold the render at its readiness timeout on every build. Every other code is a development-only `console.warn`. Each is listed at /docs/error-codes.