From hyperframes
Defines the HyperFrames HTML composition contract: data-* attributes, clips, tracks, sub-compositions, variables, media playback, and deterministic render rules. Load for structure and validation of minimal renderable projects.
How this skill is triggered — by the user, by Claude, or both
Slash command
/hyperframes:hyperframes-coreThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
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.
references/composition-patterns.mdreferences/data-attributes.mdreferences/determinism-rules.mdreferences/full-screen-motion.mdreferences/minimal-composition.mdreferences/sub-compositions.mdreferences/subagent-dispatch.mdreferences/tailwind.mdreferences/tracks-and-clips.mdreferences/variables-and-media.mdHyperFrames 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. Other concerns live in sibling skills:
hyperframes-animation — atomic motion rules + scene blueprints + per-runtime adapters (GSAP, Lottie, Three, Anime.js, CSS, WAAPI, TypeGPU)hyperframes-creative — palettes, typography, narration, beat planning, audio-reactivehyperframes-media — TTS, Whisper transcribe, background removal, captionshyperframes-registry — install blocks and components (hyperframes add)hyperframes-cli — dev loop commands (lint / validate / preview / render)For Tailwind v4 projects (hyperframes init --tailwind), see references/tailwind.md — the browser-runtime contract is distinct from Studio's Tailwind v3 setup.
| Want to… | Read |
|---|---|
| See a minimal renderable composition | references/minimal-composition.md |
| Decide between monolithic single-file and modular sub-comp architecture | references/composition-patterns.md |
Structure a modular index.html (orchestrator + slots + root audio) | references/composition-patterns.md |
| Pick a sub-comp archetype (content / driver-only / multi-scene merge / audio-reactive) | references/composition-patterns.md |
Look up a data-* attribute (root, clip, sub-comp host, legacy aliases) | references/data-attributes.md |
Use class="clip" correctly | references/data-attributes.md |
Pick a data-track-index; same-track overlap; track-index vs CSS z-index | references/tracks-and-clips.md |
Time a clip relative to another (data-start="intro + 2", crossfade overlap, chains) | references/tracks-and-clips.md |
Wire a sub-composition (host attributes, <template> wrapper, per-instance variables) | references/sub-compositions.md |
Animate inside a sub-composition (gsap.fromTo over gsap.from, seek-back behavior) | references/sub-compositions.md |
Declare variables (types, extra options, defaults, --strict-variables in CI) | references/variables-and-media.md |
Place <video> / <audio>, set volume, trim with data-media-start | references/variables-and-media.md |
Build a seekable timeline (paused, sync construction, gsap.set later-scene trap) | references/determinism-rules.md |
Avoid non-deterministic state (clocks, Math.random, repeat: -1, finite repeat formula) | references/determinism-rules.md |
Know what can / cannot be animated (visual-property allowlist; not display/visibility) | references/determinism-rules.md |
Fit text and prevent overflow (fitTextFontSize signature, <br> rule, layout contract) | references/determinism-rules.md |
| Author full-frame motion with shared backgrounds | references/full-screen-motion.md |
Work in a Tailwind v4 project (init --tailwind) | references/tailwind.md |
For animation runtime specifics (GSAP API, Lottie, Three.js, etc.) go to hyperframes-animation → adapters/<runtime>.md.
Two root forms; they are not interchangeable.
index.html) — root <div data-composition-id="…"> sits directly in <body>. No <template> wrapper. Wrapping a standalone root in <template> hides all content from the browser and breaks rendering.data-composition-src) — root <div data-composition-id="…"> must be wrapped in <template>. Without the wrapper the runtime cannot extract and mount it.⚠ Sub-composition transport rule: the runtime only clones
<template>contents into the live DOM. Everything outside the template — including<head>and any<style>/<script>/<link>that lives in<head>— is discarded. Put<style>and<script>blocks inside<template>, not in<head>.⚠ Host-id rule: in the host file,
data-composition-idon the slot must exactly equal the inner template'sdata-composition-idand thewindow.__timelines["<id>"]key. Do not add-mount/-slot/-hostsuffixes.
See references/sub-compositions.md for the file shape, host wiring, pitfall examples, and the pre-render verification checklist.
The standalone root must establish an explicitly sized box, and every ancestor between it and a height: 100% element must have a resolved height. If the root or an intermediate wrapper has no height, a flex/height:100% content container collapses to ~0 and content piles into the top-left corner (often clipping the first glyph at x=0). lint, validate, and inspect do not catch this — inspect substitutes the authored data-width/data-height for a collapsed root and reports "0 layout issues."
<body style="margin: 0">
<div
id="root"
data-composition-id="main"
data-width="1920"
data-height="1080"
data-duration="5"
style="position: relative; width: 1920px; height: 1080px; overflow: hidden"
>
<!-- Center robustly: position:absolute + inset:0 fills the sized root regardless of
intermediate wrappers; or use a flex container ONLY if its parent chain is sized. -->
<section
class="clip"
data-start="0"
data-duration="5"
data-track-index="1"
style="position: absolute; inset: 0; display: grid; place-items: center; padding: 120px 160px; box-sizing: border-box"
>
<h1>Title</h1>
</section>
</div>
</body>
Keep the padding (≥80px) on the centering container — it is the title-safe margin that stops large type touching the frame edge. See references/minimal-composition.md.
Every composition registers exactly one GSAP timeline.
gsap.timeline({ paused: true }) — the player owns playback.window.__timelines["<composition-id>"]; the key must exactly match the root's data-composition-id. Dot syntax (window.__timelines.<id> = tl) is equivalent when the id is a valid identifier; use brackets if the id contains -.async, setTimeout, Promise, or event handlers. The renderer samples after page load completes; any deferred timeline construction misses the sample.data-duration on the root, not from GSAP timeline length. Do not pad the timeline with empty tweens to set duration.master.add(sub)); the framework drives them independently.For non-GSAP runtimes (Lottie / Three / WAAPI / CSS / Anime.js / TypeGPU), the equivalent contract lives in hyperframes-animation/adapters/<runtime>.md. See references/determinism-rules.md for the cross-runtime Animation Runtime Contract.
These break the renderer — or produce silent visual bugs that lint/validate/inspect do NOT catch (rules 3, 7-8). (Synchronous timeline construction is covered above in Timeline Contract.)
Math.random() / Date.now() / performance.now() driving visuals — use a seeded PRNG.repeat: -1. Use repeat: Math.max(0, Math.floor(duration / cycleDuration) - 1) — floor, not ceil (ceil overshoots data-duration and trips the gsap_repeat_ceil_overshoot lint; max(0, …) avoids a negative repeat = infinite).<video>/<audio> must be a direct child of the host root (index.html) — never inside a sub-comp <template>, never inside a wrapper <div>; otherwise it is never decoded and renders blank/black (silent). The framework owns playback: no video.play() / audio.play() / currentTime = …. A sub-comp cannot drive host elements (selector or querySelector), so animate host media from the main timeline at global time. See references/variables-and-media.md.gsap.set() on clip elements from later scenes (they are not in the DOM yet). Use tl.set(selector, vars, time) at or after the clip's data-start.display / visibility. Animate opacity / transforms; the clip lifecycle handles show/hide.<br> in body text. Let text wrap via max-width.transform/scaleX/scaleY is a no-op on an inline <span>, and scaling an auto-width (0px) element shows nothing → invisible bars/fills. Give them display: block/inline-block/flex-item and a real width/height (e.g. width: 100% inside a sized parent).yoyo scale, back.out) need clearance at their peak size and must not straddle an overflow: hidden edge — else they overlap a neighbor or get clipped. Position for the largest frame, not the resting one.data-track-index or intentionally adjust surrounding timing.data-composition-id before wiring the host.Use hyperframes-cli for command details.
npx hyperframes lint passes (0 errors)npx hyperframes validate passes (0 console errors)npx hyperframes inspect passes, or overflow is intentionally markednpx hyperframes snapshot --at <midpoints> and eyeball each framenpx claudepluginhub heygen-com/hyperframes --plugin hyperframesScaffolds, validates, previews, and renders HyperFrames video compositions via CLI (`npx hyperframes`). Also troubleshoots the build/render environment.
CLI dev loop for HyperFrames video composition projects — scaffold, lint, visual inspect, and render via `npx hyperframes`. Use when initializing projects, debugging layout issues, or running the build/render environment.
Drives the HyperFrames CLI dev loop: scaffold, lint, validate, inspect, preview, render, and deploy to AWS Lambda. Use when running any npx hyperframes subcommand or troubleshooting the build/render environment.