HyperFrames — start here
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. The full authoring contract lives in /hyperframes-core; read it before writing composition HTML.
Below: a capability map (the domain skills, loaded on demand) and the intent router (pick a workflow for any "make me a video" request).
Capability map — the domain skills
Atomic capabilities you load on demand — not full video workflows. For "make me a video", use the intent router below.
| You want to… | Skill |
|---|---|
Author / edit an HTML composition — the data-* contract, clips, tracks, sub-compositions, variables | /hyperframes-core |
| Animate — atomic motion, scene blueprints, transitions, runtime adapters (GSAP / Lottie / Three.js / Anime.js / CSS / WAAPI / TypeGPU) | /hyperframes-animation |
Creative direction — frame.md / design.md, palettes, typography, narration, beat planning, audio-reactive | /hyperframes-creative |
| Media — TTS voiceover, background music, transcription, background removal, captions | /hyperframes-media |
Media resolve — find + freeze BGM, SFX, images, icons from HeyGen catalog into .media/ with manifest tracking | /media-use |
| CLI dev loop — init, lint, validate, inspect, preview, render, publish, doctor | /hyperframes-cli |
Install registry blocks / components (hyperframes add) | /hyperframes-registry |
Intent routing — pick a workflow
This section knows only the top-level workflows; it does not load their internal references or the domain skills above.
Before routing — confirm the input, not the spec
Routing needs to know what the video is about — its input and subject. If that's unspecified ("make a video about our thing" with no URL, product, topic, or asset), ask before entering any workflow — committing to a workflow IS the routing decision. At most two questions:
- Input — a product (URL / brief), a general website, a GitHub PR, a topic to explain, or an existing talking-head video?
Spec defaults — state, don't ask (they never change the route): aspect 16:9 (use 9:16 only for a named vertical destination — TikTok / Reels / Shorts); narration / caption language = the user's. The chosen workflow re-confirms its own specifics at its first step.
Workflow cheat-sheet
| Workflow | Use it for |
|---|---|
/product-launch-video | Selling a product (SaaS, app, company / product site) — from a URL, brief, or script → a promo. The default for any commercial URL, even if the site is only named. |
/website-to-video | Showing a site itself — a tour / showcase built from the site's own screenshots. For non-commercial sites (portfolio, blog, docs, personal, event), or when the user wants a tour, not a promo. |
/faceless-explainer | Explaining a topic / concept from text — no product, no URL; every visual is LLM-invented |
/pr-to-video | A GitHub PR / code change → changelog / feature-reveal / fix / refactor explainer |
/embedded-captions | Adding captions / subtitles to an existing talking-head video (footage untouched) |
/talking-head-recut | Packaging an existing talking-head video with designed graphic overlays — lower-thirds, data callouts, kinetic titles, pull-quotes |
/motion-graphics | A short, unnarrated, design-led motion graphic — kinetic type, a stat / chart hit, a logo sting, a lower-third overlay |
/music-to-video | A music track → a beat-synced video — lyric video, slideshow, or kinetic promo; the music drives pacing (optional user images / videos cut onto the beat grid) |
/slideshow | A presentation / pitch deck / interactive deck — discrete slides, fragments, branching, hotspots; output is a navigable deck, not a rendered video |
/general-video | Anything else — longer or multi-scene pieces, a static loop / poster, a custom composition |
/remotion-to-hyperframes | Porting an existing Remotion (React) composition to HyperFrames (migration, not creation) |
Disambiguation (only where confusable):
- Motion-first & unnarrated (under ~10s, the motion is the message) →
/motion-graphics, regardless of input. - A URL or script — ask one thing: is the site selling a product? Yes (SaaS / app / product / company site) →
/product-launch-video— a promo, and the default for any commercial URL even if the site is only named. No, or the user just wants the site shown as-is (portfolio / blog / docs / personal / event) →/website-to-video— a tour. A GitHub PR link →/pr-to-video; a concept with no product or site →/faceless-explainer. - Existing footage — plain spoken-word subtitles →
/embedded-captions; designed overlay cards →/talking-head-recut. Neither edits the footage itself (re-timing / recolor / reframe / reorder / audio is NLE editing — out of scope). - A music track is the input (an audio file, or a video to pull audio from) with no narration →
/music-to-video— the music's beats/energy drive the pacing. (Narrated pieces stay with the input-matched workflow above;/motion-graphicsis for short unnarrated motion that isn't music-driven.) - A presentation / pitch deck / interactive deck (discrete slides, navigation, presenter mode) →
/slideshow— output is a navigable deck, not a rendered video. An explicit "slideshow" request proceeds directly; an adjacent trigger ("deck / slides / presentation / convert this page") makes/slideshowconfirm it's a slideshow before authoring, and switch to the appropriate non-slideshow workflow if not. - Length is a guide, not a gate — intent picks the workflow; go to
/general-videoonly when the piece is clearly longer than ~3 min, or is a static / loop / custom format.
If the matched workflow isn't installed
Once you've picked a workflow, check it's actually available to you. If the matched workflow skill isn't installed, don't fall back to guessing — tell the user to install it first:
- Just this workflow:
npx skills add heygen-com/hyperframes --skill <workflow-name>(e.g.--skill pr-to-video— bare name, no leading/). - All workflows at once:
npx skills add heygen-com/hyperframes --all(core + every workflow, skips the picker).
After they run it, re-read the workflow's skill and continue.
Keeping skills current
HyperFrames skills are versioned. npx hyperframes init checks the installed skills against the latest on GitHub and installs/refreshes the full set whenever anything is out of date or missing — so a freshly init'd project always has the complete, latest set (and re-running init on an up-to-date project is a no-op). The check is a quick GitHub round-trip; offline (or rate-limited) it falls back to installing after a short timeout, so init never hard-fails on a network hiccup. The creation workflows scaffold with init, so starting a new project always runs this check and pulls our latest skills from GitHub when they're stale. The --skip-skills flag is currently neutered (a temporary measure while the skills.sh registry catches up): passing it no longer skips the check, so every init checks GitHub. CI/tests opt out via the HYPERFRAMES_SKIP_SKILLS=1 env var.
If a task is behaving unexpectedly, or before a long build, confirm the installed skills are current:
- Check:
npx hyperframes skills check(add--jsonfor a machine-readable verdict; exits non-zero when anything is outdated or missing). - Update:
npx hyperframes skills update— pulls the full set to the latest, installing any not yet present (same as init's install step).
The CLI also surfaces a one-line reminder when a render / lint / validate run detects stale skills.
Workflow details
/product-launch-video
- Input: A product being marketed — (a) a product URL (crawled with headless Chrome for assets + brand tokens), (b) a script / brief that names the product's site even without a link (PLV resolves + crawls it, unless the user opts out), or (c) a script with no derivable site / "don't scrape" (no-capture mode — pick a style preset that supplies palette + design system). A supplied script can be the verbatim voice-over or restructured per scene — PLV asks.
- Output: a product launch / SaaS promo as a HyperFrames composition → MP4 (sweet spot 30–90s) — the product's value is the subject, not a walkthrough of the site. For a plain tour of the site, use
/website-to-video. - Triggers: "launch video for X", "promo for our site", "explain my SaaS in a minute", "turn my script into a 60s promo", "text-only launch video, don't scrape".
/website-to-video
- Input: A website / URL whose goal is to show the site itself, not to sell a product. Best for non-commercial sites (portfolio, blog, docs, personal, event), or when the user explicitly wants a tour of a site as-is. Captured with headless Chrome for real screenshots + brand as