# Bespoke Composition (Atelier Mode) Meta-skill for **hand-authoring a composition from scratch** instead of assembling stock scene-types. This is the "hand-stitched every time" path: for hero pieces, every pixel of the look is written fresh so no two videos share a visual language. Read this whenever you've chosen **atelier mode** for a piece (see "When to use"). It does not hand you components — it routes you to the *principles, engine mechanics, and tool wiring* you need so that what you build is correct, and distinct. > The single rule that governs everything below: **reuse engine knowledge, never creative > components.** How Remotion resolves an asset is engine knowledge — reuse it freely. How a > previous video looked is a creative decision — never reuse it. ## When to use this skill (authoring mode is a proposal decision) OpenMontage separates three orthogonal axes, all locked at proposal: - `renderer_family` — creative grammar - `render_runtime` — technical engine (remotion / hyperframes / ffmpeg) - **`composition_mode`** — **templated** (assemble stock `cut.type` scenes) **vs. atelier** (hand-author) Pick **atelier** by default for: marketing, launches, explainers that must impress, brand pieces, anything single-deliverable where quality is the point. Pick **templated** for: batch output, localization variants, quick drafts, low-stakes internal clips — places where reliable sameness is fine and bespoke cost is unjustified. Present the choice to the user at proposal and log it in `decision_log` (`category: "composition_mode"`), the same way you present runtime. ### Atelier and the two runtimes The two runtimes treat "bespoke" differently — read this before assuming the doctrine maps the same way to both: - **Remotion** ships a `cut.type` registry of stock scenes (`text_card`, `stat_card`, `bar_chart`, …) dispatched by the `Explainer`/`CinematicRenderer` compositions. That's the templated default. **Atelier mode is the escape hatch** — `composition_mode: "atelier"` routes the render to `_render_via_atelier` and bypasses the registry entirely, so the agent hand-writes its own React composition under `projects//`. - **HyperFrames is inherently atelier.** There is no cut-schema in HF — every composition is a hand-authored `index.html` with `data-*` timing attributes and a GSAP timeline you wrote. The registry (`hyperframes add`) is a *block* registry (grain overlays, transitions) — it's optional inputs to your composition, not a scene catalog dispatching the whole render. **When `render_runtime: "hyperframes"` is chosen, the piece is already atelier-style; `composition_mode: "atelier"` is implicit.** The principles in this skill (art direction, scene distinctness, no hero-component spine, distinctness review) apply equally. Render via `hyperframes_compose` (or `npx hyperframes render` for hand-authored compositions — see section 5). So: if `render_runtime == "remotion"` and the piece is hero work, log a `composition_mode: "atelier"` decision. If `render_runtime == "hyperframes"`, atelier is the default behavior and you don't need to argue for it; this skill still routes you through the same principles before you write the composition. If atelier is in play (either runtime), the stock Remotion `cut.type` catalog, `hyperframes-registry` finished blocks consumed as scenes (vs as raw inputs), fixtures, and any pre-baked creative component are **off-limits** — they are frozen looks and reintroduce sameness. ## The construction route Author in this order. Each step routes you to existing knowledge — do not skip the first one. ### 1. Commit to an art direction *for this subject* — the divergence engine Before writing any component, decide a visual language that fits **this** topic and no other. Use the **`visual-style`** Layer 3 skill (CREATE mode) to lock: palette, type personality, motion character, layout system, and **one signature device** unique to this piece. Difference between videos is guaranteed here — not by withholding components, but by forcing a fresh direction each time. Write it down (a short `art-direction.md` in the project) and build to it. Ask yourself: *what visual metaphor belongs to this subject that I have not used before?* If the answer resembles a past piece, you haven't found the direction yet. ### 1.5 Plan each scene as its own composition — no hero-component spine The most insidious form of templating sneaks back in at the *scene* level: pick one striking visual (a candle, a browser frame, a score ring), then re-use it every scene with different text underneath. The piece feels custom because the hero is custom — but every scene is mechanically the same composition. That's branded slides, not a film. **Don't do that.** The signature device named in your art-direction is meant to appear in **one or at most two beats** — typically the climactic moment — not as the visual scaffolding of every scene. It earns its weight by being scarce. For each scene in the plan, answer concretely *before* writing code: - **What is this scene's primary visual subject?** It must be *different* from the previous scene's. A character. A diagram. A piece of evidence. A landscape. A typographic moment. The signature device. A void. Each scene's primary subject is its job. - **Why does this beat exist?** What does it do for the story that no other beat does? If you can collapse two scenes into one without losing meaning, you should. - **How does it differ visually from the scene before and after?** Different composition (rule of thirds vs centered vs split). Different scale (intimate close vs wide field). Different motion register (still vs busy). Different palette emphasis. Different type treatment. - **If you removed the signature device from this scene, would the scene still work?** If yes, the signature device probably doesn't belong in this scene — it's there as filler. Cut it. The reviewer enforces this as a "scene_distinctness" check (see `skills/meta/reviewer.md` → Composition Authoring Mode Review): a recorded inventory of each scene's primary subject + first frame, and an explicit answer to "do any two scenes share their primary visual subject?" Yes ⇒ CRITICAL ⇒ re-plan. The corollary: the per-scene plan is a *first-class artifact*, not implied. Write it down (in `art-direction.md` or a sibling `scenes.md`) before authoring `Composition.tsx`. ### 2. Decide the motion language — principles, not presets Reach for **principle** skills, never finished animations: - **`framer-motion`** and **`lottie-bodymovin`** — Disney's 12 principles (anticipation, staging, follow-through, slow-in/out, arc, timing, exaggeration, appeal). Runtime-agnostic; apply the *principles* in your own Remotion `spring()`/`interpolate()` code. - The HyperFrames `references/motion-principles.md` — easing as emotion, timing as weight. ### 3. Reach for a richer vocabulary only when the concept demands it **On Remotion** — most scenes are Remotion primitives. Escalate when the *idea* needs it, not by default: `gsap-*` (kinetic typography via SplitText, shape morph via MorphSVG, curved motion via MotionPath, line-draw via DrawSVG, custom easing), `threejs-*` (3D), `d3-viz` (data-driven custom charts — build the chart by hand; do **not** drop in the stock `bar_chart`/`line_chart`), `manim-*` (math), `canvas-procedural-animation` (particles/weather). **On HyperFrames** — the vocabulary lives in `/hyperframes-animation`: 36+ atomic motion **rules** (`kinetic-beat-slam`, `3d-text-depth-layers`, `motion-blur-streak`, `physics-press-reaction`, `multi-phase-camera`, `depth-of-field-blur`, …), 15+ scene **blueprints** (`kinetic-type-beats`, `comparison-split`, `dataviz-countup`, `constellation-hub`, `ticker-takeover`, `device-surface-showcase`, …), 16 **transition** families (`css-distortion`, `css-destruction`, `css-radial`, `css-light`, `css-mechanical`, …), and **7 runtime adapters** under one composition: GSAP default, plus Lottie, Three.js, Anime.js, CSS keyframes, WAAPI, and TypeGPU (GPU compute). The headline capability is `adapters/html-in-canvas-patterns.md` — capture live HTML/CSS as a GPU texture and render through WebGL/Three.js for cinematic bloom, shatter, liquid, portal effects. Use it for 1–3 hero beats per video, not every beat. **Compose 2–4 distinct atomic rules per beat** and use **at least 3 different easings across the piece** — that's the doctrine baked into the animation skill, not optional polish. For HF creative direction (palette/type/narration/beat planning) read `/hyperframes-creative`. For HF assets (TTS/BGM/SFX/transcription/background-removal) read `/hyperframes-media` or `/media-use`. For HF CLI workflow (init/lint/validate/inspect/snapshot/beats/render) read `/hyperframes-cli`. The `/hyperframes` router skill maps it all. ### 4. Get the engine mechanics right — the gotcha codex This is the only place you "reuse": the engine's solved problems. These are facts about how the framework works, not looks. **For Remotion**, study `.agents/skills/remotion-best-practices` (19 rule files: timing, transitions, text-animations, transparent video, fonts, audio, sequencing, measuring text). You may also read the stock components in `remotion-composer/src/components/` **as a mechanics codex — to learn idioms, never to import or imitate a look.** **For HyperFrames**, the composition contract is in `/hyperframes-core` (the `data-*` timing attributes — `data-start`, `data-duration`, `data-track-index` — plus the mandatory `class="clip"`, `data-composition-id`, `window.__timelines` registration, sub- composition mounts). Run `npx hyperframes lint && npx hyperframes validate` after every change — they catch missing root attrs, missing clip ids, GSAP-target unresolved, overlapping tweens, and contrast failures before render. Use `npx hyperframes snapshot . --at ` to spot-check beats visually before committing to a full render. Recurring mechanics that bite if you don't know them: - **Determinism**: no `Math.random()` / `Date.now()` per frame — use Remotion `random(seed)` or a seeded helper, or particles/easing flicker across the render. - **Per-scene duration**: `useVideoConfig().durationInFrames` returns the *composition* length, not your scene's. Drive scene-local timing from a passed `durationInFrames`/`Sequence`, not the global. - **Asset paths**: URLs and `staticFile()` (public/) work everywhere; **`