- Claude Design + HyperFrames
- For this project, your medium is
- HyperFrames compositions
- plain HTML + CSS + a paused GSAP timeline. A separate CLI ( npx hyperframes render index.html ) turns the HTML into an MP4. You are authoring the HTML files — the user runs the CLI locally. You do NOT need a CLI environment to produce these files. HyperFrames replaces your default video-artifact workflow for this project. When the user asks for a video, animation, launch teaser, editorial explainer, product tour, social reel, or any motion deliverable: Do NOT call copy_starter_component with kind: "animations.jsx" . The animations.jsx starter is the wrong format here — HyperFrames uses plain HTML + GSAP, not React Sprites. Do NOT invoke the built-in "Animated video" skill. HyperFrames replaces it for this project. Do NOT use React, Babel, or
wrapper — not just scene-1. This is the single most-missed rule in output audits.
The wrapper exists so
HyperShader.captureIncomingScene()
can hide scene content during
html2canvas
capture, preventing pre-animation from-states from leaking into the WebGL texture. Without the wrapper on a non-first scene, you'll see boxes, clipped text, or empty placeholders during the transition INTO that scene.
<
div
class
=
"
scene clip
"
id
=
"
s1
"
data-start
=
"
0
"
data-duration
=
"
5
"
data-track-index
=
"
0
"
>
<
div
class
=
"
bg-grain
"
>
div
>
<
div
class
=
"
bg-vignette
"
>
div
>
<
div
class
=
"
scene-content
"
>
<
h1
id
=
"
s1-title
"
>
…
h1
>
<
p
id
=
"
s1-sub
"
>
…
p
>
div
>
div
>
<
div
class
=
"
scene clip
"
id
=
"
s2
"
data-start
=
"
5
"
data-duration
=
"
5
"
data-track-index
=
"
0
"
style
=
"
opacity
:
0
;
"
>
<
div
class
=
"
bg-grain
"
>
div
>
<
div
class
=
"
scene-content
"
>
<
h1
id
=
"
s2-title
"
>
…
h1
>
<
p
id
=
"
s2-sub
"
>
…
p
>
div
>
div
>
Data attributes
Every timed element (scene, image, video, audio, sub-composition host) is a "clip" and must carry:
Attribute
Required
Values
id
yes
unique identifier
class="clip"
yes
literal string (scenes use
"scene clip"
)
data-start
yes
seconds, or clip-id reference (
"el-1"
,
"intro+2"
)
data-duration
required for img/div/compositions
seconds. video/audio default to media duration
data-track-index
yes
integer. same-track clips cannot overlap in time
data-media-start
no
trim offset into source (seconds) for video/audio
data-volume
no
0–1 (default 1) for audio
data-track-index
is TIMELINE layering (which clip's timeline wraps which) —
not visual z-order.
Use CSS
z-index
for stacking. Same-track clips can't overlap in time; use different tracks for simultaneous clips or put them on the same track with non-overlapping windows.
Composition roots (the outer
index.html
and any
-wrapped sub-comp root) also need:
Attribute
Required
Values
data-composition-id
yes
unique ID. root uses
"main"
by convention
data-start
yes
root:
"0"
data-duration
yes
seconds. takes precedence over GSAP timeline length
data-width
yes
pixel width (1920 for 16:9, 1080 for 9:16, 1080 for 1:1)
data-height
yes
pixel height (1080 for 16:9, 1920 for 9:16, 1080 for 1:1)
data-composition-src
no
path to external HTML sub-composition (
compositions/…
)
Timeline contract
Every composition has exactly ONE timeline, created
paused: true
.
Register it on
window.__timelines[""]
— the key MUST match the root's
data-composition-id
exactly.
The composition root's DOM
id
attribute should also equal its
data-composition-id
(convention:
). Nothing in the runtime enforces this, but consistent IDs make
#main
selectors in your timeline code and the
__timelines
key one word apart — preventing the
id="root"
/
data-composition-id="main"
/
__timelines["main"]
three-way drift that's easy to typo.
Never call
.play()
on the timeline — the player/render engine drives playback via frame-accurate seeking.
Framework auto-nests sub-comp timelines — DO NOT manually
.add()
them to the root timeline.
Duration comes from
data-duration
on the root, NOT from GSAP timeline length.
Construct synchronously at page load. No
async
/
await
/
setTimeout
wrapping timeline code.
Video and audio
Video elements must be
muted playsinline
. Browsers silently block audio playback on inline video, so HyperFrames
never uses