S

slideshow

by @heygen-comv
4.9(120)

This skill generates structured, navigable HyperFrames slideshows, incorporating scene definitions, speaker notes, fragment control, and branching logic. It addresses the pain points of time-consuming and less interactive traditional presentation creation. Users can efficiently produce professional and expressive interactive presentations, suitable for product pitches, technical sharing, and various other scenarios.

slideshowpresentationinteractivecontent-creationdeckGitHub
Installation
npx skills add https://github.com/heygen-com/hyperframes --skill slideshow
compare_arrows

Before / After Comparison

1 组
Before

Users had to manually write complex HTML and JSON structures to define slides, scenes, timelines, speaker notes, and branching logic. This consumed significant time for structure building and logic validation, leading to errors and maintenance difficulties.

After

This skill automatically generates HyperFrames-compliant slideshow structures and metadata, with built-in validation. It drastically reduces manual coding and debugging time, ensuring the accuracy and consistency of presentations.

SKILL.md

Slideshow authoring contract

A HyperFrames slideshow is a normal HyperFrames composition — scenes, clips, GSAP timelines — with one extra ingredient: a JSON island that declares which scenes are slides and how they connect. The player's SlideshowController reads the island and turns the continuous GSAP timeline into a discrete, navigable deck.

Read /hyperframes-core first for the base composition contract (clips, tracks, data-* attributes, determinism rules). This skill covers only what is new: the island schema, slide writing rules, fragments, branching, validation, and the wrapping component.

Intent confirmation

If the user explicitly asks for a slideshow, slide show, or HyperFrames slideshow, proceed with this skill.

If the skill triggered from an adjacent request such as "presentation", "pitch deck", "deck", "interactive deck", or "convert this page", pause before authoring and frame the choice before asking for confirmation. Briefly explain that a HyperFrames slideshow means a runnable deck with discrete slides, built-in navigation and presenter mode, editable speaker notes, shared media handling, and validation before handoff. For source-page conversions, also mention that the goal is to preserve the original page's visual design, interactions, motion, and media behavior while translating page movement into slide-to-slide transitions.

Then ask a short confirmation question:

Do you want this as a HyperFrames slideshow?

Use a yes/no choice UI when the environment provides one; otherwise ask the question in plain text.

Do not implement the slideshow until the user says yes. If they say no, stop using this skill and switch to the appropriate non-slideshow workflow.


The two pieces

1. Scenes — declared the normal way

Every slide is backed by a scene. Declare scenes with data-composition-id, data-start, data-duration, and data-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>

Branch slides (reachable only via a hotspot, excluded from the main line) are declared exactly the same way — they just appear only in a slideSequences entry in the island, not in the main slides array.

2. The JSON island — one script block per composition

Add exactly one <script type="application/hyperframes-slideshow+json"> block to the composition HTML. It holds all slideshow metadata:

<script type="application/hyperframes-slideshow+json">
  {
    "slides": [...],
    "slideSequences": [...]
  }
</script>

The island is the single source of truth for slide order, notes, fragment hold-points, hotspots, and branch sequences. Keep it near the top of the <body>, before the scene divs, so it is easy to find.

Do not hide the slideshow manifest behind an alternate <script type="application/json"> block plus runtime code that creates the island. The present command reads the composition HTML statically and expects the real application/hyperframes-slideshow+json island to already be present.


Schema

SlideshowManifest (the top-level island object)

{
  "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
}
FieldRequiredNotes
sceneIdyesMust match a scene's data-composition-id exactly (or provide explicit startTime/endTime). The lint rule resolves scenes by data-composition-id.
notesnoPresenter-only text. Never shown to the audience.
fragmentsnoArray of times (seconds) within the slide's [start, end] range — see Fragments below.
hotspotsnoInteractive overlays that trigger a branch — see Branching below.
startTimenoOptional. Override the matched scene's time bounds; defaults to the scene's start/end.
endTimenoOptional. Override the matched scene's time bounds; defaults to the scene's start/end.
ttsScript, ttsAudioUrl, ttsDurationMsnoReserved. 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 }
}
FieldRequiredNotes
idyesUnique within the slide.
labelyesTooltip / button text shown to the audience.
targetyesMust match a SlideSequence.id in slideSequences.
regionnoPercentage-of-slide bounding box: {x, y, w, h} in 0–100. Omit to render the hotspot as a full-slide labeled button instead.

SlideSequence

{
  "id": "market-deep-dive",
  "label": "Market sizing methodology",
  "slides": [{ "sceneId": "mkt-1" }, { "sceneId": "mkt-2" }]
}

slides inside a sequence uses the same SlideRef shape as the main line. Fragments and nested hotspots are allowed.


Slide writing rules

These are hard constraints, not suggestions. A slide that violates them will be outright replaced when a reviewer sees it.

  • Headline is a complete-sentence claim, not a label. Write "SMBs spend 14 hours/week on manual scheduling" not "Scheduling problem". The sentence should stand alone if the visual is ignored.
  • One idea + one visual per slide. If you are tempted to add a second bullet cluster or a second chart, split the slide.
  • Lead with the punchline. The strongest point goes first — on the slide and in the deck order. Investors read left-to-right, top-to-bottom, and they stop.
  • Bottom-up market sizing only. Never write "$50B TAM" without showing the math. Build from unit economics up: accounts × ACV, or transactions × take-rate.
  • Font minimum 30pt equivalent. At 1920×1080, a headline is 72–96px; body copy is 48px. Never go below 40px for any text the audience must read.

Porting source pages

When converting an existing page into a slideshow, source fidelity is part of the contract. Do not replace source-specific widgets with simplified approximations unless the user explicitly asks for a redesign.

  • Preserve the original page's visual design, motion language, interactive behavior, media behavior, and presentation affordances as closely as practical. When the slideshow system supports presenter mode, include speaker notes using the shared editable-notes behavior rather than a deck-specific implementation.
  • Port mechanical visuals from the source DOM/CSS/JS as exactly as practical: custom players, canvas visualizers, timelines, playheads, stems, expanding circles, hover states, and other interactive details should survive the conversion.
  • Treat native <video> / <audio> elements as the source of truth for any custom media chrome, canvas visualizer, waveform, beat grid, or playhead. Wire the source's media events (play, pause, timeupdate, seeking, seeked, ended, ratechange, volumechange) and derive visual state from media.currentTime; do not run a separate timer that can drift away from actual playback.
  • Every copied <video> or <audio> with src must have HyperFrames timing attributes before lint: data-start and data-duration, plus data-has-audio="true" when audible native audio should be preserved. Use the scene's time range for slide-specific media; for user-controlled evidence videos that may be played from multiple focused slides, use a deck-wide range. Do not leave preload="none" on media; use metadata or auto.
  • Resolve source font tokens before validation. If preserving custom source fonts, add @font-face rules for local/captured font files. If using system fallbacks, replace tokenized declarations such as font-family: var(--f-body) with concrete render-safe stacks such as system-ui, sans-serif or ui-monospace, monospace; do not leave var(...) as the font family value.
  • Audit the source for atypical page movement, especially behavior driven by scroll, wheel, touch, hash state, resize, or a requestAnimationFrame loop. Treat fixed viewports with translated/scaled "world" layers, parallax, pinned panels, horizontal scrollers, scroll-scrubbed timelines, section snapping, and zoom-to-element cameras as source behavior. Scroll is often the source's transition trigger, so preserve the transition by extracting its progress stops, easing, and camera/focus states, then re-host that motion on slideshow navigation through timeline positions, fragments, or a reusable player/harness hook. Standalone wrappers that jump to slide hold-points still need an explicit navigation-camera transition hook; computing per-slide camera transforms is not enough. Do not simulate a literal page-scroll-down transition inside the slide; the viewer should feel camera travel/zoom from one focal point to another, not see a webpage being scrolled. Keep each slide-to-slide camera move continuous: avoid intermediate route stops that reverse x/y direction or zoom unless the source visibly does that at the same boundary. A transition that darts around before landing is worse than a simpler direct focal move.
  • Preserve the source's media crop semantics. Treat screenshots, tweets/social posts, product UI captures, charts, docs, code, leaderboards, and any image with readable text as content evidence, not decorative media: use the source aspect ratio (height: auto) or object-fit: contain inside a stable frame. Use object-fit: cover only when the source did, or for intentionally decorative/background/cinematic thumbnails. After fitting these captures into a slide, inspect all four edges for truncated text, logos, controls, or captions; a visible crop on meaningful content is a bug unless the source itself cropped it.
  • If a behavior is generic to slideshows, put it in the player/controller or in a reusable skill snippet. Do not solve it with one-off deck scripts.
  • Stacked scene frames must never block interaction on the active slide. Hidden frames need both visual hiding and event gating:
.scene-frame {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}

.scene-frame.is-active {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}

If visibility is driven imperatively, set all three properties (opacity, visibility, and pointerEvents) in the visibility controller. opacity: 0 alone still leaves an invisible layer that can swallow clicks.


Fragments: reveal hold-points within a slide

A fragment is an absolute composition-timeline time (seconds) within a slide's [start, end] range where the controller should hold a reveal state.

How it works:

  1. Player enters a fragmented slide — seeks directly to fragments[0] and holds there.
  2. User presses Next (or →) — controller seeks to fragments[1] and holds.
  3. After the last fragment, Next advances to the next slide.
  4. A slide without fragments enters at a rest frame inside the slide, usually its midpoint, not exactly at slide.end.

Fragment times must fall within [start, end] (inclusive of both bounds). The lint rule rejects only fragments outside that range (time < start or time > end).

Fragment times are absolute composition-timeline positions — the same coordinate space as data-start — not offsets relative to the scene's start.

Navigation is seek-driven, not play-driven. The controller never starts playback just to move between fragments; each navigation command is a deterministic seek to the target hold time. Design fragment states so they are correct at the target timeline time.


Branching: hotspots and slide sequences

Branch slides are real scenes in the same composition timeline. They are listed only under slideSequences and are excluded from main-line navigation — the player never visits them unless a hotspot fires.

Navigation model:

  • Clicking a hotspot pushes {sequenceId, slideIndex: 0} onto the nav stack and enters the branch's first slide.
  • back() pops the stack and returns to the exact parent slide (the one that held the hotspot).
  • backToMain() clears the entire stack and returns to the root slide.
  • Breadcrumb renders from the stack: Main deck › Market sizing methodology › Slide 2.
  • The slide counter inside a branch is scoped to that sequence (1 of 2, not the main-deck total).

What to avoid:

  • Do not add branch scene IDs to the main slides array. They must appear only inside a slideSequences entry. The lint rule flags overlap.
  • Branch scenes are included in the continuous timeline, so a naive linear video export would include them. Export reads main-line slides only (deferred; flagged in the spec).

Worked example: 3-slide deck with fragments and a branch

Scene HTML (skeleton)

<body style="margin: 0">
  <script type="application/hyperframes-slideshow+json">
    {
      "slides": [
        {
          "sceneId": "hook",
          "notes": "Open with the stat. Pause on the $40B number."
        },
        {
          "sceneId": "pro

...

User Reviews (0)

Write a Review

Effect
Usability
Docs
Compatibility

No reviews yet

Statistics

Installs400.9K
Rating4.9 / 5.0
Version
Updated2026年10月23日
Comparisons1

User Rating

4.9(120)
5
37%
4
43%
3
13%
2
5%
1
2%

Rate this Skill

0.0

Compatible Platforms

🤖claude-code

Timeline

Created2026年6月25日
Last Updated2026年10月23日
🎁 Agent Knowledge Cards
Survey