Files
OpenMontage/skills/meta/bespoke-composition.md
T
calesthio f9f86ac9f8 feat(atelier): forbid hero-component spine; captions/text dedup rule (F12 + F9)
F12 — Hero-component spine is a templating anti-pattern. The first
atelier proof (alexandria-fire) leaned on a single candle as scaffolding
under every scene with different text below — same hero, different
caption — which is exactly the "branded slides" pattern atelier was
supposed to break. The signature device is meant to appear in ONE or
at most two beats (typically the climactic moment), not as the visual
scaffolding of every scene. Each scene must earn its own composition:
a different primary visual subject, a different scale, a different motion
register. Doctrine added as step 1.5 in skills/meta/bespoke-composition.md
("Plan each scene as its own composition") plus a reviewer
scene_distinctness gate enforced at compose stage — the reviewer samples
one representative frame per scene and refuses to pass if two or more
scenes share their primary visual subject.

F9 — Captions/on-screen-text dedup. When a SerifLine reads the script
verbatim AND auto-captions emit the same text, the piece looks amateurish
even when the rest is beautiful. Rule added under engine mechanics: decide
once per piece whether captions add meaning (numbers, names, translations,
attributions) or are accessibility subtitles echoing narration — never
both for the same content. Reviewer gate at compose stage compares active
caption text against on-screen text in the same time window.

Both gates are CRITICAL; the publish-stage check was updated to expect
six (was four) resolved atelier findings.

Self-audit of alexandria-fire under the new rules: 4 of 5 scenes share
the candle as their primary visual subject — would now flag CRITICAL
scene_distinctness and require re-planning. (Re-author the piece in a
follow-up; the doctrine is the deliverable here.)
2026-06-27 11:36:51 -07:00

11 KiB

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 now separates three orthogonal axes, all locked at proposal:

  • renderer_family — creative grammar
  • render_runtime — technical engine (remotion / hyperframes / ffmpeg)
  • composition_modetemplated (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.

If atelier is chosen, the stock scene-type catalog, the hyperframes-registry blocks, fixtures, and any finished 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

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).

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 Remotion works, not looks. 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.

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; <Audio> rejects file:// (only <OffthreadVideo>/<Img> accept absolute file://). Put audio/video in a per-project public dir and reference via staticFile. Mirror the resolveAsset helper.
  • GSAP-in-Remotion: use a paused timeline and .seek(frame/fps) — never requestAnimationFrame — so frames render deterministically.
  • Fonts: loadFont() from @remotion/google-fonts/<Name> at module scope, once.
  • Captions vs on-screen text — pick one role, never both for the same content. Decide once per piece, before authoring: are captions adding meaning the spoken words can't carry (a number, a name, a translation, a quote attribution), OR are they accessibility subtitles echoing the narration? If your scene already displays a SerifLine that reads the script verbatim, do NOT also emit an auto-caption with the same text — the doubled phrase looks amateurish even when the rest of the scene is beautiful. Empty captions=[] in props, or scope captions only to scenes where the on-screen text differs from what's being said.

5. Render through the atelier path (project-local, throwaway)

Bespoke scenes are throwaway and project-local — they never enter the shared src/ registry.

  • Author under remotion-composer/projects/<slug>/ (gitignored). It needs its own Remotion entry (index.tsx + a Root registering only this composition) so it reuses the composer's node_modules and stays out of the global Root.tsx. The entry MUST live under remotion-composer/ for the bundler to resolve remotion.
  • Keep media in a small per-project public dir and pass it as public_dir so renders don't copy the bloated shared public/.
  • Render via video_compose operation="render" with:
edit_decisions = {
  "render_runtime": "remotion",
  "composition_mode": "atelier",
  "bespoke": {
    "entry": "remotion-composer/projects/<slug>/index.tsx",
    "composition_id": "<id registered in that entry's Root>",
    "props_path": "<absolute path to props.json>",
    "public_dir": "<absolute path to the project's public dir>",
    "scale": 0.5,          // 0.5 for a fast draft; drop for the 1080p final
    "crf": 18,             // crisp final
    "concurrency": 8
  }
}

No asset_manifest or cuts are required in atelier mode — the composition owns its own assets.

Guardrails so this doesn't backfire

  • Distinctness review (replaces conformance review). Before final render, ask: could this be any other product's video? Does it reuse a look I've made before? If yes, the art direction failed — return to step 1. This is the inverse of "does it match the reference."
  • No silent fallback to stock. "Keep it simple" applies to mechanics (a 10-line spring is fine), never to design (simple ≠ reaching for text_card). If you catch yourself adding a stock cut.type to a hero piece, stop.
  • Cost honesty. Atelier costs more agent tokens and iteration than templated. Say so at proposal so the user opts in knowingly. Quality varies more without a stock baseline — mitigate with strong principle skills (above) and the distinctness review, not by reintroducing reuse.
  • Checkpoint cadence. Follow skills/meta/checkpoint-protocol.md: present script + scene plan for approval BEFORE generating assets, then a footage/asset checkpoint, then a first-render checkpoint. Do not batch-generate ahead of sign-off.

Worked precedent (for the workflow, not the look)

The first atelier piece was the Phantom Reach explainer (projects/phantom-reach-explainer/): Playwright-captured app footage with a PII-blur layer → per-sentence TTS stitched with silence beats → free Pixabay music → hand-authored Remotion scenes (custom intro, score-ring, agentic flow, CTA) on a one-off violet theme. Study its process (capture → timing → props builder → bespoke scenes → render). Do not reproduce its visual language — the next piece must look nothing like it. That is the whole point.

See also: skills/meta/animation-runtime-selector.md (runtime + library routing), AGENT_GUIDE.md → "Composition Authoring Mode".