skill by
@heygenThe HyperFrames composition contract — build one renderable project. Use for composition structure, the `data-*` timing attributes, `class="clip"`, tracks, sub-compositions, variables, framework-owned media playback, deterministic-render rules, and validation. Also covers Tailwind projects and the STORYBOARD.md / SCRIPT.md plan formats. Read before writing composition HTML.
Permissions
Files
The HyperFrames composition contract — build one renderable project. Use for composition structure, the `data-*` timing attributes, `class="clip"`, tracks, sub-compositions, variables, framework-owned media playback, deterministic-render rules, and validation. Also covers Tailwind projects and the STORYBOARD.md / SCRIPT.md plan formats. Read before writing composition HTML.
Install
It’s free, and every skill you add syncs into every AI tool on your computer, instantly.
Version history
HyperFrames renders video from HTML. A composition is an HTML file whose DOM declares timing with data-* attributes, whose animation runtime is seekable, and whose media playback is owned by the framework.
This skill is the technical contract — how to build one hyperframes project. The body below is the build guide; per-topic detail lives in references/ (index next), read on demand. Other concerns live in the sibling domain skills — hyperframes-animation, hyperframes-creative, media-use, hyperframes-cli, hyperframes-registry. The capability map in /hyperframes says what each one covers.
| File | Read it to… |
|---|---|
references/minimal-composition.md | start from the smallest renderable composition skeleton |
references/composition-patterns.md | choose monolithic vs modular; structure a modular index.html; pick a sub-comp archetype |
references/data-attributes.md | look up any data-* (root / clip / sub-comp host / legacy aliases); use class="clip" |
references/tracks-and-clips.md | pick data-track-index, handle same-track overlap / z-index, time a clip relative to another |
references/creator-editing-recipes.md | copy truthful cut/trim/reorder/retime/freeze/camera/mask/crossfade/audio editing recipes and their limits |
references/sub-compositions.md | wire a sub-composition (host attrs, <template>, per-instance vars) and animate inside it |
references/variables-and-media.md | declare variables; place <video>/<audio>, set volume, trim |
references/determinism-rules.md | build a seekable timeline; determinism bans; the animatable-property allowlist; layout / text fit |
references/full-screen-motion.md | author full-frame motion with shared backgrounds |
references/storyboard-format.md | author a STORYBOARD.md plan (+ the parsed manifest) |
references/review-loop.md | run the plan → sketch → build review passes on a live board — shared by every storyboard-planning workflow |
references/production-loop.md | take an approved plan to a delivered video — the stage dependencies (audio, frames, assembly, transitions, captions, verify, deliver) a freeform build follows directly |
references/brief-contract.md | the brief's ground rules — mode derivation (collaborative / autonomous), shared field registry, question invariants (the asking itself lives in /hyperframes → the intent layer) |
references/brief-format.md | author BRIEF.md — the confirmed intent document a workflow's Setup writes and every later step reads |
references/script-format.md | author the optional SCRIPT.md locked narration |
references/subagent-dispatch.md | map subagent dispatch verbs (parallel fan-out / background / wait) to your harness |
references/frame-worker-core.md | the shared frame-worker role contract — each narrative workflow's packet builder prepends it to that workflow's sub-agents/frame-worker.md delta |
references/tailwind.md | work in a Tailwind v4 project (init --tailwind; runtime contract differs from Studio's v3) |
For animation runtime specifics (GSAP API, Lottie, Three.js, etc.) go to hyperframes-animation → adapters/<runtime>.md.
index.html) — root <div data-composition-id="…"> sits directly in <body>, no <template> wrapper (wrapping it hides all content and breaks rendering).data-composition-src) — root must be wrapped in <template>.⚠ Transport rule: the runtime only clones
<template>contents; everything outside (incl.<head>styles/scripts) is discarded — put<style>/<script>inside the template. ⚠ Host-id rule: the host slot'sdata-composition-idmust exactly equal the inner template'sdata-composition-idand thewindow.__timelines["<id>"]key — no-mount/-slot/-hostsuffix.
File shape, host wiring, and the pre-render checklist → references/sub-compositions.md.
The standalone root needs an explicit sized box (width/height in px), and every ancestor down to a height:100% element must have a resolved height — otherwise a flex/100% child collapses to ~0 and content piles into the top-left corner. Do not rely on automated gates alone to catch this; inspect a snapshot. Skeleton → references/minimal-composition.md.
Each composition registers exactly one gsap.timeline({ paused: true }) at window.__timelines["<id>"] (key = root data-composition-id), built synchronously at page load. Render duration = root data-duration, not timeline length. Don't manually nest sub-timelines into the host. Full contract (incl. non-GSAP runtimes) → references/determinism-rules.md + hyperframes-animation/adapters/.
Two rules that lint does catch, but only after the fact — write them right the first time:
data-start="0" (alongside data-composition-id/data-width/data-height); omitting it fails lint with root_composition_missing_data_start.transform with a GSAP tween on the same property — the CSS value and the tween's start fight and lint rejects it with gsap_css_transform_conflict. Set the initial state inside the tween with gsap.fromTo(el, { x: -40 }, { x: 0 }) instead of a CSS transform: translateX(-40px).Surfaced here; full rationale in the linked reference. Do not violate:
Math.random / network / input-state; no repeat: -1 (use a finite count). → determinism-rules.mddisplay or raw visibility. GSAP autoAlpha and zero-duration timeline boundary sets are the only visibility exceptions, and only on non-clip elements or wrappers inside a clip. The framework alone controls .clip visibility. Do not gsap.set later-scene clips at page load. → determinism-rules.md<br> in body text; transformed elements must be block-level + sized; pulsing absolute decoratives need peak clearance. → determinism-rules.md<video>/<audio> work at any nesting depth (including inside a sub-comp <template> or wrapper); the framework owns playback and seeks/decodes media wherever it lives. The one caveat is timelines, not placement: a sub-comp timeline can't animate host-root elements. → variables-and-media.mdid must be unique across the assembled page; inside a sub-comp, prefix ids with the composition id (#<id>-hero). Duplicate <video>/<img> ids render blank — the producer injects frames by getElementById, and cross-file dupes slip past lint. → composition-patterns.mdposition:absolute; inset:0), never on the composition root itself — the producer's frame compositing can drop the root element's own background (the frame renders black) even though preview/snapshot show it correctly. → composition-patterns.mddata-track-index or adjust surrounding timing intentionally.data-hidden on any composition element hides it in BOTH preview and render, overriding its time window; it is non-destructive/reversible and toggled by Studio's timeline eye icon.data-composition-id before wiring the host.Use hyperframes-cli for command details
npx hyperframes check passes (0 findings across lint, runtime, layout, motion, and contrast)npx hyperframes snapshot --at <midpoints> and eyeball each framenpx hyperframes preview --background for review (the user can edit anything in Studio's timeline, and the server survives the invoking command)npx hyperframes render only after the user approvesIn these kits
Works with
Claude, Codex, Cursor & more