> ## Documentation Index
> Fetch the complete documentation index at: https://motionly.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Motion System

> Beats, layouts, and showcases: select complete motion design ideas instead of placing primitives.

Motionly's motion system is a component layer above the native engine. Instead of
positioning rectangles and inventing keyframes, you select named blocks and the
engine supplies the geometry, spacing rhythm, hierarchy, and choreography.

```
prompt / author
  → beats            pacing and focus
  → layouts          composition
  → showcases        product presentation
  → semantic components / archetypes
  → .motion AST → scene graph → evaluator → renderer
```

Every block lowers to ordinary Motionly elements — `group`, `overlay`, `image`,
`text`, `transition`, and animations. Nothing new reaches the renderer, and the
result stays fully editable source.

## Where the code lives

The `registry/` folder holds **generated JSON manifests only** — a searchable
index for `motionly catalog` and `motionly add`. The implementation is TypeScript
in `src/`:

| Block              | Implementation                            | What it owns                                                                  |
| ------------------ | ----------------------------------------- | ----------------------------------------------------------------------------- |
| Layouts            | `src/motion-system/layout.ts`             | 12 deterministic solvers, 8px rhythm, stagger math                            |
| Showcases          | `src/motion-system/showcase.ts`           | Device geometry, screen crop, glare, entrance, idle, push                     |
| Beats              | `src/motion-system/beats.ts`              | Time windows, camera framing, storyboard plan                                 |
| Transitions        | `src/motion-system/transitions.ts`        | Shared element, object morph, layout morph, camera                            |
| Asset intelligence | `src/motion-system/asset-intelligence.ts` | Classification → recommended presentation                                     |
| Selection metadata | `src/motion-system/metadata.ts`           | The index the AI selects from                                                 |
| UI components      | `src/semantic/component-structures.ts`    | Per-type builders: dashboard, browser, terminal, pricing card, laptop, editor |
| Vector sources     | `src/semantic/vector-registry.ts`         | Licensed glyphs, sizes, capabilities, part names                              |
| Lowering           | `src/semantic/motion-lowering.ts`         | AST → AST pass that expands the three block kinds                             |
| Registry generator | `scripts/generate-registry.ts`            | Emits `registry/**/registry-item.json` from the catalog                       |

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.

```motion theme={null}
beat intro {
  duration 5s
  focus title
  label "Brand introduction"
}

beat reveal {
  duration 7s
  focus product
  zoom 1.25
  label "Product reveal"
}
```

| Property                       | Meaning                                                       |
| ------------------------------ | ------------------------------------------------------------- |
| `start`                        | Absolute start. Omit to run directly after the previous beat. |
| `duration`                     | Beat length. Omit to share the remaining canvas time evenly.  |
| `focus`                        | Focal element the camera frames.                              |
| `zoom`, `cameraX`, `cameraY`   | Camera framing for this beat.                                 |
| `route`                        | What keeps the beat performing. See below.                    |
| `transition`                   | Transition into the beat.                                     |
| `from`, `to`                   | Endpoints for paired transitions.                             |
| `transitionDuration`, `easing` | Transition timing.                                            |
| `label`                        | Storyboard label, kept on the scene for the editor.           |

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](/animation/motion-doctrine).

| Route           | What it is                                                              |
| --------------- | ----------------------------------------------------------------------- |
| `stagedReveals` | Content held back and paid off in stages                                |
| `cameraIntent`  | A mapped camera path: establish, travel, arrive                         |
| `uiLife`        | The product behaves over time: progress advances, counts tick           |
| `sequence`      | Elements act out a beat: a card files into a stack                      |
| `cursorLed`     | A cursor walks the eye to a control and its click ignites the next beat |
| `hold`          | Deliberate stillness — the only route that may hold a frame still       |

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 child `parent NAME`; the
solver assigns position, size, and a staggered entrance.

```motion theme={null}
layout capabilities {
  type bentoGrid
  columns 3
  gap 40
  beat features
}

component planCard {
  parent capabilities
  type pricingcard
}
```

Available types: `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](/animation/motion-doctrine).

## Showcases

A showcase turns one real asset into a finished product presentation.

```motion theme={null}
import "/assets/dashboard.png" as dashShot

showcase product {
  type dashboardShowcase
  media dashShot
  headline "Every metric, live"
  behavior push highlight
  beat reveal
}
```

| Type                     | Presents                                                 |
| ------------------------ | -------------------------------------------------------- |
| `productHero`            | One asset with a glow bed and headline                   |
| `phoneShowcase`          | Mobile screen with bezel, notch, glare                   |
| `browserShowcase`        | Web product with chrome, traffic lights, URL pill        |
| `laptopShowcase`         | Desktop product on a laptop with base and shadow         |
| `appWindow`              | Native app window with a slim titlebar                   |
| `dashboardShowcase`      | Dashboard with sidebar rail and camera push              |
| `screenshotPresentation` | Frameless media with elevation and reflection            |
| `uiWalkthrough`          | Window, step chip, and a focus ring on the acting region |

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.

| Kind            | Behavior                                       | Needs `from`/`to` |
| --------------- | ---------------------------------------------- | ----------------- |
| `sharedElement` | One element hands off to another               | yes               |
| `objectMorph`   | One subject becomes another                    | yes               |
| `layoutMorph`   | An arrangement rearranges into another         | yes               |
| `cameraMove`    | The camera reframes the persistent composition | no                |
| `continuous`    | Nothing cuts; the composition keeps evolving   | no                |
| `cut`           | Explicit hard change                           | no                |

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 into `logo`, `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:

```motion theme={null}
layout features {
  type bentoGrid
  columns 3
}
```

Each layout and showcase folder in `registry/` additionally holds a worked example
composition, purely so you can read one or start from it:

```bash theme={null}
npx @coppsary/motionly catalog --type layout      # list blocks; [example] marks those with one
npx @coppsary/motionly catalog --show bentoGrid   # print the example, write nothing
npx @coppsary/motionly add bentoGrid              # copy it in as a starting file
```

`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

```bash theme={null}
npm run inspect:motion -- path/to/project.motion --strict
```

Beyond validity, the inspector audits motion quality: entrances over budget,
cascades that queue instead of accelerate or spread past one beat, stretches where
nothing is in flight, elements with no area, elements never inside the canvas, and
similarly sized unrelated elements stacked on each other. Findings are advisory
unless `--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.
