Loading...
Loading...
Author a HyperFrames slideshow composition — a presentation, pitch deck, or interactive deck with discrete slides, fragment reveals, branching sequences, and hotspot navigation. Read when the request is to build or edit a slideshow, presentation, or pitch deck as a HyperFrames composition.
npx skill4agent add heygen-com/hyperframes slideshowSlideshowController/hyperframes-coredata-*data-composition-iddata-startdata-durationdata-label<div
data-composition-id="problem"
data-start="0"
data-duration="8"
data-label="The problem"
data-width="1920"
data-height="1080"
>
<!-- clips go here -->
</div>slideSequencesslides<script type="application/hyperframes-slideshow+json"><script type="application/hyperframes-slideshow+json">
{
"slides": [...],
"slideSequences": [...]
}
</script><body>SlideshowManifest{
"slides": [
/* SlideRef[] — the main line, in order */
],
"slideSequences": [
/* SlideSequence[] — off-line branch sequences */
]
}SlideRef{
"sceneId": "problem",
"notes": "Lead with the pain, not the company.",
"fragments": [3.5, 5.2, 7.0],
"hotspots": [
/* SlideHotspot[] */
],
"ttsScript": null,
"ttsAudioUrl": null,
"ttsDurationMs": null
}| Field | Required | Notes |
|---|---|---|
| yes | Must match a scene's |
| no | Presenter-only text. Never shown to the audience. |
| no | Array of times (seconds) within the slide's |
| no | Interactive overlays that trigger a branch — see Branching below. |
| no | Optional. Override the matched scene's time bounds; defaults to the scene's start/end. |
| no | Optional. Override the matched scene's time bounds; defaults to the scene's start/end. |
| no | Reserved. Schema fields exist but TTS playback is not yet wired. Omit unless you are pre-populating for a future build. |
SlideHotspot{
"id": "h1",
"label": "How did we calculate this?",
"target": "market-deep-dive",
"region": { "x": 60, "y": 10, "w": 35, "h": 20 }
}| Field | Required | Notes |
|---|---|---|
| yes | Unique within the slide. |
| yes | Tooltip / button text shown to the audience. |
| yes | Must match a |
| no | Percentage-of-slide bounding box: |
SlideSequence{
"id": "market-deep-dive",
"label": "Market sizing methodology",
"slides": [{ "sceneId": "mkt-1" }, { "sceneId": "mkt-2" }]
}slidesSlideRef[start, end]startfragments[0]fragments[1]slide.end[start, end]data-startslideSequences{sequenceId, slideIndex: 0}Main deck › Market sizing methodology › Slide 21 of 2slidesslideSequences<body style="margin: 0">
<script type="application/hyperframes-slideshow+json">
{
"slides": [
{
"sceneId": "hook",
"notes": "Open with the stat. Pause on the $40B number."
},
{
"sceneId": "problem",
"notes": "Walk through each pain point one at a time.",
"fragments": [11.0, 15.0],
"hotspots": [
{
"id": "h1",
"label": "Where does the $40B figure come from?",
"target": "market-detail",
"region": { "x": 55, "y": 60, "w": 40, "h": 20 }
}
]
},
{
"sceneId": "solution",
"notes": "One sentence: what we do and who it is for."
}
],
"slideSequences": [
{
"id": "market-detail",
"label": "Market sizing methodology",
"slides": [{ "sceneId": "mkt-math", "notes": "Bottom-up: 2.3M SMBs × $17k ACV." }]
}
]
}
</script>
<!-- Slide 1 — hook -->
<div
data-composition-id="hook"
data-start="0"
data-duration="6"
data-label="The hook"
data-width="1920"
data-height="1080"
style="position: relative; width: 1920px; height: 1080px; overflow: hidden; background: #0a0a0a"
>
<section
class="clip"
data-start="0"
data-duration="6"
data-track-index="1"
style="position: absolute; inset: 0; display: grid; place-items: center"
>
<h1 id="hook-headline" style="font-size: 80px; color: #fff; font-family: sans-serif">
SMBs lose $40B/year to manual scheduling
</h1>
</section>
</div>
<!-- Slide 2 — problem (3 fragments) -->
<div
data-composition-id="problem"
data-start="6"
data-duration="15"
data-label="The problem"
data-width="1920"
data-height="1080"
style="position: relative; width: 1920px; height: 1080px; overflow: hidden; background: #0a0a0a"
>
<section
class="clip"
data-start="6"
data-duration="15"
data-track-index="1"
style="position: absolute; inset: 0; padding: 120px 160px; box-sizing: border-box"
>
<h2 id="pain-headline" style="font-size: 64px; color: #fff; font-family: sans-serif">
Three gaps operators can not close
</h2>
<p id="pain-1" style="font-size: 48px; color: #ccc; opacity: 0; font-family: sans-serif">
No-shows cost 23% of booked revenue
</p>
<p id="pain-2" style="font-size: 48px; color: #ccc; opacity: 0; font-family: sans-serif">
Manual reminders take 4h/week per staff
</p>
<p id="pain-3" style="font-size: 48px; color: #ccc; opacity: 0; font-family: sans-serif">
Rescheduling friction drives 40% churn
</p>
</section>
</div>
<!-- Slide 3 — solution -->
<div
data-composition-id="solution"
data-start="21"
data-duration="8"
data-label="The solution"
data-width="1920"
data-height="1080"
style="position: relative; width: 1920px; height: 1080px; overflow: hidden; background: #0a0a0a"
>
<section
class="clip"
data-start="21"
data-duration="8"
data-track-index="1"
style="position: absolute; inset: 0; display: grid; place-items: center"
>
<h2 id="solution-headline" style="font-size: 72px; color: #fff; font-family: sans-serif">
Acme automates scheduling for service SMBs — no-shows down 80% in 90 days
</h2>
</section>
</div>
<!-- Branch slide — excluded from main line -->
<div
data-composition-id="mkt-math"
data-start="29"
data-duration="7"
data-label="Market math"
data-width="1920"
data-height="1080"
style="position: relative; width: 1920px; height: 1080px; overflow: hidden; background: #111"
>
<section
class="clip"
data-start="29"
data-duration="7"
data-track-index="1"
style="position: absolute; inset: 0; display: grid; place-items: center"
>
<p id="mkt-formula" style="font-size: 56px; color: #fff; font-family: sans-serif">
2.3M SMBs × $17k ACV = $39B serviceable market
</p>
</section>
</div>
<script>
window.__timelines = window.__timelines || {};
// Slide 2 fragment entrance animations
gsap.registerPlugin(); // load any plugins before use
const tl = gsap.timeline({ paused: true });
window.__timelines["problem"] = tl;
// Insert positions are absolute composition-timeline times (same as data-start / fragment values).
tl.from("#pain-1", { opacity: 0, y: 20, duration: 0.4 }, 11.0);
tl.from("#pain-2", { opacity: 0, y: 20, duration: 0.4 }, 15.0);
// pain-3 lands at end of slide
tl.from("#pain-3", { opacity: 0, y: 20, duration: 0.4 }, 13.0);
</script>
</body>sceneId"hook""problem""solution""mkt-math"data-composition-idmkt-mathslideSequencesslides11.015.0problem[6, 21]regionx: 55, y: 60, w: 40, h: 20window.__timelines.play()<hyperframes-slideshow><hyperframes-player><hyperframes-slideshow>
<hyperframes-player src="deck.html"></hyperframes-player>
</hyperframes-slideshow><hyperframes-slideshow>window.open('?mode=audience')BroadcastChannel('hf-slideshow')hyperframes preview --slideshowskills/slideshow/references/standalone-harness.mdnpx hyperframes lintslide.sceneIddata-composition-idhotspot.targetslideSequence[start, end]