group, overlay, image,
text, transition, and animations. Nothing new reaches the renderer, and the
result stays fully editable source.
Where the code lives
Theregistry/ folder holds generated JSON manifests only — a searchable
index for motionly catalog and motionly add. The implementation is TypeScript
in src/:
Run
npm run registry:generate after changing a definition; the JSON is a build
artifact, never edited by hand.
Beats
A beat is a change in focus, not a slide. Beats never clear the composition, so objects persist and transform across the whole film.
Attach content to a beat with
beat NAME. The block’s entrance delay resolves
from the beat start, so timing is a storyboard decision instead of a pile of
hand-tuned delays.
Routes
Every beat is owned by exactly one sustained-motion route. Idle drift is not sustained motion — see the Motion Doctrine.
The route is inferred when omitted: a camera move becomes
cameraIntent, two or
more attached blocks become stagedReveals, and anything else is an explicit
hold. An authored route is validated against what the beat actually contains —
claiming cameraIntent without moving the camera is a compile error, because a
route is a claim about how the beat performs.
Layouts
A layout solves composition. Declare it, then give each childparent NAME; the
solver assigns position, size, and a staggered entrance.
heroLayout, splitLayout, bentoGrid, featureGrid,
masonryGrid, deviceStack, logoWall, comparisonLayout, timelineLayout,
carousel, gallery, floatingCollage.
Properties: type, columns, gap, width, height, itemWidth,
itemHeight, order (linear, center-out, reverse), stagger, beat,
parent, delay, layer.
An authored value always wins. Set x on one child and the solver fills in the
rest. Fixed-aspect children such as semantic components are fitted inside their
slot rather than stretched to fill it.
The layout also owns the group’s arrival motion: gaps shrink across the cascade so
it accelerates, travel and duration scale by composition weight (the focal tile
arrives with more presence than its support), opacity snaps rather than fades, and
the whole group lands inside one beat however many items it holds. Those numbers
are in the Motion Doctrine.
Showcases
A showcase turns one real asset into a finished product presentation.
Properties:
type, media, headline, caption, label, width, behavior,
accent, surface, focusX, focusY, beat, parent, delay, duration,
layer.
Behaviors are float (idle drift), push (camera push on the subject),
highlight (focus ring), and still (suppress idle motion).
The screen clips its media, so a tall capture crops instead of distorting. With
no media, the showcase renders an honest “Add product media” empty state.
Transitions
Transitions transform what is on screen; they never fade the frame.
When a beat changes focus and names no transition, the planner defaults to
cameraMove. When focus is held, it defaults to continuous. Paired kinds are
never inferred, because both endpoints must exist for the scene graph to accept
the project.
Asset intelligence
Imports are classified intologo, icon, screenshot, ui, illustration,
photo, video, avatar, chart, or unknown. Filename intent wins, then
declared type, then geometry — a portrait capture is a phone screenshot, a
landscape one is a desktop interface. Each kind maps to the showcases that frame
it and, for groups, the layouts that arrange it.
Examples
Everything comes by default. Blocks are compiled into the engine — there is no install step, no dependency to add, nothing to fetch. Write this and it works:registry/ additionally holds a worked example
composition, purely so you can read one or start from it:
add is a convenience that copies that example into compositions/. Skipping it
costs you nothing.
These examples are generated from the definitions, so they cannot drift, and the
test suite audits every one against the doctrine with zero tolerance — the catalog
is held to the rules it publishes.
Checking a project
--strict is given.
Working with archetypes
archetype remains valid and unchanged for slide-style shots. Use beats,
layouts, and showcases when the composition should persist and evolve; use
archetypes for a self-contained shot with its own scene root.