Any part of the finish except the grain's fps can be a track, { at, to, ease }, which Kinetic reads at each frame's time.
A track given in place of a field is that field's amount.
The overlays the page shows follow the tracks on every seek.
See A finish that changes.
The finish takes diffuse, { amount, radius }, with a radius of 16 px by default.
It blurs the whole frame and mixes the blur over it, the look of a soft-focus filter.
Like the bloom and the aberration, it is in the rendered file only.
moves(list) builds a camera from a list of moves, each with an ease, lag, overshoot, kick, swing, drift, or steady-rate dolly.
Moves add together, so they blend, and each one ends exactly on its values.
look(eye, at) points the camera at a point, and a move can end on one.
See moves(list, options) and look(eye, at).
cameraAt(t, tracks, options) returns the camera's numbers at time t, { x, y, z, pan, tilt, roll, zoom }, with any shake added.
depth()'s camera option takes these numbers.
depth(z, { detail, camera }) draws a layer 1 to 8 times finer.
It is for a layer the camera magnifies while it is turned, which Chrome otherwise draws at its CSS size and stretches.
camera takes the numbers from cameraAt(), and the style depth() returns gains zoom.
A detail outside 1 to 8, or one given without the camera, is KN-100.
land() and arrival() time a move by when it arrives #
land(t, at, duration, ease) is ramp() started early enough that the move arrives, within 3% of its end, at at, such as a beat.
arrival(ease, duration) gives the seconds from a move's start until it arrives.
For a spring ease, that time is the same at any duration.
timeOf('beat 9') is the time of beat 9, the same as tempo().at(9), and timeOf('frame 170') is that frame's time at the composition's rate.
data-start reads neither form.
tempo().frame(n) gives beat n's time on its nearest frame, and onFrame(t) gives the time of the frame nearest t.
A second file, kinetic.25d.js, loaded after kinetic.wf.js, adds solids(target, options).
It draws boxes, cages, and faces of your own from 3D coordinates into an SVG element as paths, which it culls, clips at a near plane, sorts far to near, and shades by one light through a ramp of colors, with a rim and glows.
The same values draw the same SVG whatever was drawn before.
Loaded without kinetic.wf.js, the file prints KN-100 and does nothing.
See Solids in 2.5D.
config({ encode: { codec, bitrate, audioCodec, audioBitrate } }) sets the encoder for every render() that does not give its own, including the preview bar's Render button.
A wrong field or value is KN-100.
data-viewmode shows an element in the video or on the page alone #
data-viewmode="render" shows an element in the video alone, and data-viewmode="live" shows one only while the page plays.
viewmode() and the store's viewmode are 'render' while check() or render() runs or a render captures, and 'live' otherwise.
The preview bar shows a frame as the render draws it #
On a piece with a finish or a shutter, the preview bar has an As Rendered button.
It pauses the piece and lays the frame over the stage as the render draws it, with the shutter and the finish.
A frame step or a scrub draws the new frame, and playing, a render, or a check turns the button off.
It needs what a render needs.
A notice before a render inside another site's frame #
In a page inside another site's frame, which may block the render's download, the preview bar's Render button first says so, with Render anyway and Close.
config({ frameNotice: false }) turns the notice off.
See The preview bar.
Development builds warn when a page has a second composition root beside the first (KN-155).
Kinetic drives the first one alone.
See the diagnostics list.
Under layout:, check.cjs lists text outside the safe area at rest, text cut off at the frame's edge, text over other text, and text under its contrast floor, measured against what is behind it.
--no-layout skips the pass.
check.cjs takes --pace calm, lively, or bold.
It measures the share of frames near still, the snaps a minute, the longest stretch near still, the range of brightness, the share in smooth ramps, and the tones in use.
It compares each with the expression dial's target and marks each miss.
--seam reports the change from the last frame to frame 0, and --jumps reports every pair of frames that changes far more than the frames around it.
--diff a,b reports the change between two frames, and --isolate hides each selector in turn over that pair and prints how much of the change it takes away.
--strip tiles the frames --frames saves into one numbered strip.png.
check.cjs takes --view render, live, or both, the view the whole check runs in.
The skill's guide has directions for lively and bold pieces #
The guide gains expression directions for lively and bold pieces, with the dial's targets, the laws a reel follows, and two directions, Flat Field and Flythrough.
It also gains patterns for cutting to a track and for solids in 2.5D, and the Plus Jakarta Sans and Lora pairing.
Its new rules cover moves timed by when they arrive, a move on every beat, and a whole number of dashes on a circle.
Fixed
An embed page with sound keeps its speaker button #
Under embed, a page with sound keeps Kinetic's speaker button, the only sound control an embed has.
See Sound in the preview and Embedding.
Under embed, elements added later are hidden too #
Under embed, an element the page adds beside the composition after it loads is hidden, as the elements there at load are.
See Embedding.
The fit scales a root sized as a share of its container #
With the fit on, a root that the CSS sizes as a share of its container is scaled by its laid-out width, and fills the space as a root sized in pixels does.
See The config options.
The guide's lesson questions turn their choices off after the right answer #
A lesson question built from the skill's guide turns its choices off once the right answer is picked.
Before, a wrong pick made after the right one showed its text while the explanation played and turned Next off.
See A question that explains a wrong answer.
render()'s default video bitrate is 16 Mbps, up from 8 Mbps, which keeps the detail of grain, glows, and soft gradients.
Pass bitrate to render(), or set it in config({ encode }), for another rate.
See render(options).
The preview bar's Render button uses the page's settings #
The preview bar's Render button renders with the shutter, the finish, and the encoder set in config({ shutter, finish, encode }).
Once the render is done, the bar reads "render complete", with the file's name, its frames, and the time it took, until the next thing done on the bar.
With the preview bar or config({ fit: true }), the stage also fits the height of the window above the bar, so a portrait stage shows whole.
In a frame, the page around it sizes the stage as before.
The skill's check.cjs checks the render view by default, with data-viewmode="render" elements shown and data-viewmode="live" elements hidden.
--view live checks the page as it plays.
The guide sends a reel, a brand film, a sting, or a title to a direction #
For a showreel, a brand film, a sting, or a title at the lively or bold end of the dial, the skill's guide uses one of its directions in place of the default style.
The script tags in the skill's guide load @wildflowerjs/kinetic@0.2.
0.1.2 2026-11-01
Added
text() takes any axis the outlines were baked with #
text() takes any axis the outlines were baked with, by its tag, such as Shantell Sans's BNCE, as a line or letter value beside wght and slnt.
The outline baker offers every axis a font has.
See Type with a weight per letter and the Outline baker.
Fixed
A page's own sound button starts the sound with one press #
config({ sound: true }) called from a click resumes the audio, so a page's own sound button starts the sound with one press.
Kinetic's corner speaker no longer turns the sound off again.
See Sound in the preview.
render() places a canvas with a border or padding #
render() draws a canvas that has a border or padding and object-fit in its place in Chrome 157 and later, which paints a canvas into its content box.
Before, the canvas came out a few pixels off.
See Canvases in a render.
captions() balances its lines.
Between sentence ends and pauses, the words take the fewest lines maxWords and maxChars allow, about equal in length and broken after a comma near the middle.
A short fragment is no longer left on a line of its own.
See captions(t, words, options).
KN-131 says what to do on a page opened from disk #
On a page opened from disk, whose address starts with file:, KN-131 says that the page cannot fetch the files beside it, and to serve the folder or load the data as a script.
KN-170 prints when 3 of the last 30 seeks took longer than 8 ms, and gives the slowest and a typical seek time.
Before, it printed on the first slow seek.
See The check script.
KN-151's suggestion, and the skill's guide, put a lesson's frame-loop work on a store's tick().
A store's tick() runs in both modes, so it returns early unless the page is in interactive mode and holding.
See Scenes.
The skill's guide gains eight more type pairings and six more palettes (Tol Bright, Viridis Ordered, Neon Stage, Canopy, Lavender Clinic, and Solarized Light).
It uses italics sparingly, where they suit the words.
See Type pairings and Color palettes.
The guide has a pattern for a rate the learner controls #
The skill's guide gains a pattern for a rate the learner controls.
The video sums the rate from the scripted settings, and the lesson advances it while a step holds, both from one rate function.
The guide's starter lesson lays out in normal flow #
The starter lesson lays its heading and line out in normal flow, so a heading that wraps no longer runs into the line.
The guide also gains a pattern for ink plates out of register, boil()'s detail for large shapes, and a centered line that types in place.
Its intake asks nothing when the request already gives enough to build.
0.1.1 2026-10-31
Fixed
render() of a DOM composition in Chrome 157 and later #
render() of a DOM composition works in Chrome 157 and later, where HTML-in-Canvas is on by default.
Kinetic marks the composition root drawable for the render, which Chrome now requires of an element it draws, and takes the mark off after.