From 3f1950b806e72fece41552077b491f1c8c6e8b28 Mon Sep 17 00:00:00 2001 From: Ular Kimsanov Date: Mon, 26 Oct 2026 08:38:20 +0000 Subject: [PATCH] docs(examples): the inspiration page, with films and remixes to start from (#6383) * docs(examples): the inspiration page, with films and remixes to start from The Examples page becomes Inspiration: two rows of films made with HyperFrames, then 41 remixes of popular videos, each crediting and linking the original post, with how to remix it in the Studio app. The rows play one film at a time, since a second playing film drops the page from 120 to 30 fps, and they get a Pause button. The block and template tables stay. * docs(examples): remixes honour reduced motion; one film while the dialog is open Remix previews now follow reduced motion (read on the first render, stopped if it turns on), and each film is a button that plays it on purpose with sound. The film rows stop their previews while a full film plays in the dialog, so only one film plays at a time. Two remixes get the credit handles the app lists for them. * docs(examples): a motion setting change keeps remix cards as they are The shelf keeps the reduced-motion setting in a ref, so a change no longer re-renders it and remounts every card: a playing remix, its focus and its open instructions stay. * docs(examples): one film at a time across the whole Inspiration page The dialog paused only the film-row previews, so a chosen remix kept playing behind it. Any video that starts with sound now makes each remix card stop its own, and the film rows rest their previews while a film with sound plays anywhere on the page. * docs(examples): remix cards and film-row controls in the docs palette The remix cards used Tailwind zinc greys and white, the film rows the old green focus ring and fixed tints; they now use the palette tokens, so they sit on the beige ground and in the Night theme like the rest. --- docs/custom.css | 132 ++++++ docs/examples.mdx | 519 ++++++++++++++++----- docs/snippets/film-rows.jsx | 196 ++++++++ docs/snippets/remix-shelf.jsx | 130 ++++++ scripts/check-docs-snippet-motion.test.mjs | 6 +- 5 files changed, 852 insertions(+), 131 deletions(-) create mode 100644 docs/snippets/film-rows.jsx create mode 100644 docs/snippets/remix-shelf.jsx diff --git a/docs/custom.css b/docs/custom.css index 22577f427e..c2b2b67f42 100644 --- a/docs/custom.css +++ b/docs/custom.css @@ -1688,3 +1688,135 @@ pre.shiki { .hf-day-play { display: block; width: 100%; padding: 0; border: 0; background: none; cursor: pointer; border-radius: 0.5rem; } .hf-day-play:focus-visible { outline: 2px solid var(--hf-brand); outline-offset: 2px; } + +/* Showcase rows: two tracks of films drifting in opposite directions, each track twice its films for a seamless loop. */ +.hf-film-rows { + display: grid; + gap: 0.6rem; + margin: 1.25rem 0 1.5rem; + overflow: hidden; + border-radius: 0.6rem; + mask-image: linear-gradient(90deg, transparent, #000 4%, #000 96%, transparent); +} +.hf-film-row { + overflow: hidden; +} +.hf-film-track { + display: flex; + width: max-content; + animation: hf-film-drift 90s linear infinite; +} +.hf-film-row.is-reverse .hf-film-track { + animation-direction: reverse; + animation-duration: 105s; +} +@keyframes hf-film-drift { + to { + transform: translateX(-50%); + } +} +.hf-film-card { + position: relative; + height: 11.5rem; + margin: 0 0.6rem 0 0; + padding: 0; + border: 0; + border-radius: 0.5rem; + overflow: hidden; + background: #1a1a1a; + cursor: pointer; + flex: none; +} +.hf-film-card video { + display: block; + width: 100%; + height: 100%; + object-fit: cover; +} +.hf-film-card:focus-visible { + outline: 2px solid var(--hf-brand); + outline-offset: 2px; +} +.hf-film-label { + position: absolute; + left: 0; + right: 0; + bottom: 0; + padding: 1.2rem 0.6rem 0.45rem; + font-size: 0.72rem; + line-height: 1.25; + text-align: left; + color: #fff; + background: linear-gradient(transparent, rgb(0 0 0 / 0.7)); +} +.hf-film-label b { + display: block; + font-weight: 600; + opacity: 0.75; + text-transform: uppercase; + letter-spacing: 0.06em; + font-size: 0.62rem; +} +.hf-film-dialog { + position: fixed; + inset: 0; + margin: auto; + height: fit-content; + width: min(92vw, 1100px); + padding: 0; + border: 0; + border-radius: 0.75rem; + background: #111; + color: #fff; +} +.hf-film-dialog::backdrop { + background: rgb(0 0 0 / 0.7); +} +.hf-film-dialog video { + display: block; + width: 100%; + max-height: 80vh; + background: #000; +} +.hf-film-dialog-bar { + display: flex; + justify-content: space-between; + align-items: center; + gap: 1rem; + padding: 0.6rem 0.9rem; + font-size: 0.85rem; +} +.hf-film-dialog-bar button { + font: inherit; + color: inherit; + background: transparent; + border: 1px solid rgb(255 255 255 / 0.4); + border-radius: 999px; + padding: 0.25rem 0.8rem; + cursor: pointer; +} +@media (prefers-reduced-motion: reduce) { + .hf-film-track { + animation: none; + } + .hf-film-row { + overflow-x: auto; + } +} +@media (max-width: 640px) { + .hf-film-card { + height: 9rem; + } +} + +.hf-film-rows.is-paused .hf-film-track { animation-play-state: paused; } +.hf-film-pause { display: block; margin: 0.5rem 0 0 auto; padding: 0.25rem 0.75rem; border: 1px solid var(--hf-border-color-light); + border-radius: 999px; font-size: 0.8125rem; font-weight: 600; background: transparent; color: inherit; } + +/* Remix cards in the docs palette: frosted cream on the ground (a Night card in dark mode), ink text, black pill. */ +.hf-remix-card { background: var(--hf-background-light); border-color: var(--hf-ui-border); backdrop-filter: blur(12px); } +.hf-remix-media { background: var(--hf-surface2); } +.hf-remix-name { color: var(--hf-heading); } +.hf-remix-credit, .hf-remix-help { color: var(--hf-text-secondary); } +.hf-remix-credit a { color: inherit; } +.hf-remix-btn { background: var(--hf-heading); color: var(--hf-background); } diff --git a/docs/examples.mdx b/docs/examples.mdx index 84f6e3a060..bc35aed874 100644 --- a/docs/examples.mdx +++ b/docs/examples.mdx @@ -1,143 +1,410 @@ --- -title: "Examples" -description: "Watch finished HyperFrames videos, inspect real production projects, or start from a working template." +title: "Inspiration" +description: "Videos people made, remixed in HyperFrames: launch films, motion graphics and talking-head edits. Find one you like and remix it in the Studio app." --- -import { DocsVideo } from "/snippets/docs-video.jsx"; +import { RemixShelf } from "/snippets/remix-shelf.jsx"; +import { FilmRows } from "/snippets/film-rows.jsx"; import { ReplicaCompare } from "/snippets/replica-compare.jsx"; -import { ExamplePlayer } from "/snippets/example-player.jsx"; -## What HyperFrames can make +export const motion = [ + { + "id": "jake-pond", + "name": "Pond: a new Linux OS", + "ratio": "16/9", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/jake-pond-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/jake-pond-result.jpg", + "handle": "@bflycomputer", + "post": "https://x.com/bflycomputer/status/2082496873655648632" + }, + { + "id": "jake-lovable", + "name": "Lovable: Aesthetics Update", + "ratio": "16/9", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/jake-lovable-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/jake-lovable-result.jpg", + "handle": "@Lovable", + "post": "https://x.com/Lovable/status/2053874566460752191" + }, + { + "id": "jake-figma-draw", + "name": "Figma Draw", + "ratio": "16/9", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/jake-figma-draw-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/jake-figma-draw-result.jpg", + "handle": "@figma", + "post": "https://x.com/figma/status/1920168282751185360" + }, + { + "id": "remix-anduril", + "name": "Anduril: AI Grand Prix", + "ratio": "1/1", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/remix-anduril-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/remix-anduril-result.jpg", + "handle": "@anduriltech", + "post": "https://x.com/anduriltech/status/2016233946607141290" + }, + { + "id": "remix-grok-bot", + "name": "Grok Bot: now on more plans", + "ratio": "16/9", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/remix-grok-bot-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/remix-grok-bot-result.jpg", + "handle": "@bot", + "post": "https://x.com/bot/status/2090852881373311369" + }, + { + "id": "remix-kimi-k3", + "name": "Kimi K3 teaser", + "ratio": "16/9", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/remix-kimi-k3-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/remix-kimi-k3-result.jpg", + "handle": "@Kimi_Moonshot", + "post": "https://x.com/Kimi_Moonshot/status/2081757327146045450" + }, + { + "id": "remix-jordanarchivess", + "name": "How do you communicate that", + "ratio": "4/3", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/remix-jordanarchivess-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/remix-jordanarchivess-result.jpg", + "handle": "@jordanarchivess", + "post": "https://x.com/jordanarchivess/status/2107536262894915762" + }, + { + "id": "remix-firecrawl", + "name": "Firecrawl Free Keyless", + "ratio": "16/9", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/remix-firecrawl-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/remix-firecrawl-result.jpg", + "handle": "@ericciarla", + "post": "https://x.com/ericciarla/status/2093375835679977570" + }, + { + "id": "remix-authorize-once", + "name": "Authorize Once, Everyone Connected", + "ratio": "16/9", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/remix-authorize-once-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/remix-authorize-once-result.jpg", + "post": "https://x.com/ClaudeDevs/status/2091953609185657251", + "handle": "@ClaudeDevs" + }, + { + "id": "remix-zaro", + "name": "Zaro: apps and agents on your context", + "ratio": "16/9", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/remix-zaro-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/remix-zaro-result.jpg", + "handle": "@ZaroAI_", + "post": "https://x.com/ZaroAI_/status/2070084796378747316" + }, + { + "id": "remix-polymarket-perps", + "name": "Polymarket Perps", + "ratio": "16/9", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/remix-polymarket-perps-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/remix-polymarket-perps-result.jpg", + "handle": "@Polymarket", + "post": "https://x.com/Polymarket/status/2095530373274816595" + }, + { + "id": "remix-web-noise", + "name": "From web noise to working UI", + "ratio": "16/9", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/remix-web-noise-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/remix-web-noise-result.jpg", + "post": "https://x.com/firecrawl/status/2057495269785358384", + "handle": "@firecrawl" + }, + { + "id": "remix-linear-loops", + "name": "Linear Loops", + "ratio": "16/9", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/remix-linear-loops-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/remix-linear-loops-result.jpg", + "handle": "@linear", + "post": "https://x.com/linear/status/2079233260161323371" + }, + { + "id": "remix-glyph", + "name": "Glyph: GPU typography for the web", + "ratio": "640/461", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/remix-glyph-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/remix-glyph-result.jpg", + "handle": "@pmndrs", + "post": "https://x.com/pmndrs/status/2100980802091708818" + }, + { + "id": "remix-hermes-omarchy", + "name": "Hermes in Omarchy", + "ratio": "1/1", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/remix-hermes-omarchy-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/remix-hermes-omarchy-result.jpg", + "handle": "@NousResearch", + "post": "https://x.com/NousResearch/status/2097403926072987986" + }, + { + "id": "remix-iskra-light", + "name": "Iskra Light", + "ratio": "5/4", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/remix-iskra-light-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/remix-iskra-light-result.jpg", + "handle": "@world_is_web", + "post": "https://x.com/world_is_web/status/2084694934657892557" + }, + { + "id": "remix-elevenlabs-reception", + "name": "Reception by ElevenLabs", + "ratio": "16/9", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/remix-elevenlabs-reception-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/remix-elevenlabs-reception-result.jpg", + "handle": "@ElevenLabs", + "post": "https://x.com/ElevenLabs/status/2100262886916358361" + }, + { + "id": "remix-cyera", + "name": "Cyera brand video", + "ratio": "16/9", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/remix-cyera-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/remix-cyera-result.jpg", + "handle": "@motionimo", + "post": "https://x.com/motionimo/status/2103703350017433670" + }, + { + "id": "remix-harvey", + "name": "Harvey", + "ratio": "16/9", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/remix-harvey-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/remix-harvey-result.jpg", + "handle": "@harvey", + "post": "https://x.com/harvey/status/2089722668761432349" + } +]; -Every film below is 100% HyperFrames — HTML rendered frame by frame, no other tool. They are grouped by what they show off. Where a source project is public, the card links to it. +export const aroll = [ + { + "id": "aroll-aiwithsachi", + "name": "Top 5 plugins to install in Claude", + "ratio": "9/16", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/reference/aroll/aiwithsachi-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/reference/aroll/aiwithsachi-result.jpg", + "handle": "@aiwithsachi", + "post": "https://www.instagram.com/reel/Dc7G9Pxu_1O/" + }, + { + "id": "aroll-tenfoldmarc", + "name": "17 video effects Claude can create", + "ratio": "9/16", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/reference/aroll/tenfoldmarc-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/reference/aroll/tenfoldmarc-result.jpg", + "handle": "@tenfoldmarc", + "post": "https://www.instagram.com/reel/Def9pj5TWtA/" + }, + { + "id": "aroll-careerwithriya", + "name": "6 essential skills to transform your career", + "ratio": "9/16", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/reference/aroll/careerwithriya-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/reference/aroll/careerwithriya-result.jpg", + "handle": "@careerwithriya", + "post": "https://www.instagram.com/reel/Ddd57MBszhc/" + }, + { + "id": "aroll-harpercarrollai", + "name": "10 Days of AI Basics, Day 1", + "ratio": "9/16", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/reference/aroll/harpercarrollai-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/reference/aroll/harpercarrollai-result.jpg", + "handle": "@harpercarrollai", + "post": "https://www.instagram.com/reel/C4eNPF3PdpG/" + }, + { + "id": "aroll-mattfarmerai", + "name": "Best AI image generators, October 2026", + "ratio": "9/16", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/reference/aroll/mattfarmerai-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/reference/aroll/mattfarmerai-result.jpg", + "handle": "@mattfarmerai", + "post": "https://www.instagram.com/reel/DeCtQ_9JACg/" + }, + { + "id": "aroll-nocode-joshua", + "name": "10/10 Claude Skills for marketing", + "ratio": "9/16", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/reference/aroll/nocode-joshua-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/reference/aroll/nocode-joshua-result.jpg", + "handle": "@nocode.joshua", + "post": "https://www.tiktok.com/@nocode.joshua/video/7663973344026397960" + }, + { + "id": "aroll-mpaige13", + "name": "Granola + Claude Skills", + "ratio": "9/16", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/reference/aroll/mpaige13-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/reference/aroll/mpaige13-result.jpg", + "handle": "@mpaige13", + "post": "https://www.instagram.com/reel/DY5X72kxE-4/" + }, + { + "id": "aroll-brockmesarich", + "name": "These 5 GitHub Repos Give You Thousands of Free Claude Skills", + "ratio": "9/16", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/reference/aroll/brockmesarich-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/reference/aroll/brockmesarich-result.jpg", + "handle": "Brock Mesarich", + "post": "https://www.youtube.com/shorts/rxOcBowQcS0" + }, + { + "id": "aroll-drcintas", + "name": "Motion graphics in seconds", + "ratio": "9/16", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/reference/aroll/drcintas-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/reference/aroll/drcintas-result.jpg", + "handle": "@drcintas", + "post": "https://www.instagram.com/reel/DPoXbzZjb8J/" + }, + { + "id": "aroll-itsbetterwithai", + "name": "Astra makes complete AI videos inside ChatGPT", + "ratio": "9/16", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/reference/aroll/itsbetterwithai-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/reference/aroll/itsbetterwithai-result.jpg", + "handle": "@itsbetterwithai", + "post": "https://www.instagram.com/reel/DdTzYbkCkvc/" + }, + { + "id": "aroll-kevinstratvert", + "name": "Stop Paying for 5 AI Tools", + "ratio": "9/16", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/reference/aroll/kevinstratvert-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/reference/aroll/kevinstratvert-result.jpg", + "handle": "Kevin Stratvert", + "post": "https://www.youtube.com/shorts/1fA5j5_5TRY" + }, + { + "id": "aroll-dan-martell-tools", + "name": "What's the best AI tool right now?", + "ratio": "9/16", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/dan-martell-tools-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/dan-martell-tools-result.jpg", + "handle": "Dan Martell", + "post": "https://www.youtube.com/shorts/mk1zJd9Rm4c" + }, + { + "id": "aroll-ali-abdaal-workflow", + "name": "5 tools I use every day", + "ratio": "9/16", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/ali-abdaal-workflow-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/ali-abdaal-workflow-result.jpg", + "handle": "@aliabdaal", + "post": "https://www.youtube.com/shorts/S2AZbZ_K8vY" + }, + { + "id": "aroll-ali-abdaal-archival", + "name": "Face over archival art", + "ratio": "9/16", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/ali-abdaal-archival-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/ali-abdaal-archival-result.jpg", + "handle": "@aliabdaal", + "post": "https://www.youtube.com/shorts/Ksjt_I8rDrE" + }, + { + "id": "aroll-ali-abdaal-dm", + "name": "Reads a DM, answers it", + "ratio": "9/16", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/ali-abdaal-dm-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/ali-abdaal-dm-result.jpg", + "handle": "Ali Abdaal", + "post": "https://www.youtube.com/shorts/jCyhEO3h-Ik" + }, + { + "id": "aroll-cindy-zhu-ranking", + "name": "Webcam ranking, 1 to 10", + "ratio": "9/16", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/cindy-zhu-ranking-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/cindy-zhu-ranking-result.jpg", + "handle": "@cindiezhu", + "post": "https://www.tiktok.com/@cindiezhu/video/7694049166972013831" + }, + { + "id": "aroll-hook-open-loops", + "name": "Hook, lead, open loops", + "ratio": "9/16", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/hook-open-loops-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/hook-open-loops-result.jpg", + "post": "https://www.instagram.com/reel/DambEp1igDW/", + "handle": "@realskytan" + }, + { + "id": "aroll-hundred-days-story", + "name": "100 days with stickers and photo cards", + "ratio": "9/16", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/hundred-days-story-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/hundred-days-story-result.jpg", + "post": "https://www.instagram.com/reel/Dd6vHlQgpok/", + "handle": "@anyway.julia" + }, + { + "id": "aroll-khris-sheer-founder", + "name": "The Founder Experiments, Ep. 1", + "ratio": "9/16", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/khris-sheer-founder-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/khris-sheer-founder-result.jpg", + "handle": "@khris.sheer", + "post": "https://www.tiktok.com/@khris.sheer/video/7491715587895430402" + }, + { + "id": "aroll-john-tagudin-capso", + "name": "Tool demo with callouts", + "ratio": "9/16", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/john-tagudin-capso-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/john-tagudin-capso-result.jpg", + "handle": "@john.tagudin", + "post": "https://www.tiktok.com/@john.tagudin/video/7524883942328126728" + }, + { + "id": "aroll-ugc-rachelll", + "name": "AI creator with product", + "ratio": "9/16", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/ugc-rachelll-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/ugc-rachelll-result.jpg", + "handle": "@ugc.rachelll", + "post": "https://www.tiktok.com/@ugc.rachelll/video/7616996050066345246" + }, + { + "id": "aroll-gusfiraa-meitu", + "name": "Photo glow-up in an editing app", + "ratio": "9/16", + "result": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/gusfiraa-meitu-result.mp4", + "resultPoster": "https://static.heygen.ai/hyperframes-oss/desktop/viral-clone/gusfiraa-meitu-result.jpg", + "handle": "@gusfiraa", + "post": "https://www.tiktok.com/@gusfiraa/video/7668295832994598162" + } +]; -### Product & launch films +Every video on this page was made with HyperFrames: launch films, cartoons, explainers, 3D, logo stings, live-coded +music. Click one to watch it with sound. -A whole product cut into a launch film — its own screens, type and colour. + -
-
- -
HeyGen × StripeProduct launch, 4K · 100% HyperFrames
-
-
- -
HyperFrames launchThe framework's own launch · source included
-
-
- -
Website → videoA live site becomes a promo · source included
-
-
- -
SpaceX explainerData and motion at scale · source included
-
-
- -
K3 promoShort product spot · 100% HyperFrames
-
-
+## Remix a video you like -### The tooling, shown working +The fastest way to a video you love is to start from one. Every video below is a remix: someone's original, rebuilt +in HyperFrames with new words, people and brand. Hover to play. Like one? Choose **Remix in Studio** and make your +own version; see [Reference any video](/studio-app/reference-video) for how it works. -Each film is HyperFrames demonstrating one of its own features. +### Launch films and motion graphics -
-
- -
Agent skillsThe skill system · 100% HyperFrames
-
-
- -
KeyframesSeek-safe animation · 100% HyperFrames
-
-
- -
Timeline editorStudio timeline · source included
-
-
- -
Studio inspectorEditing on the canvas · source included
-
-
- -
VariablesOne composition, many versions · source included
-
-
- -
Cloud renderingRender on HeyGen's cloud · source included
-
-
+Product launches and type-led motion, rebuilt from the original's cuts, timing and effects. -### Motion, sound & effects + -Motion is the message — kinetic type, beat-synced cuts, texture and VFX. +### Talking-head edits -
-
- -
Texture launchMotion design · 100% HyperFrames
-
-
- -
VFX reelShaders and effects · 100% HyperFrames
-
-
- -
Music to videoCuts synced to a track · 100% HyperFrames
-
-
- -
Sound & musicSFX and music with the CLI · source included
-
-
- -### Workflows & integrations - -A PR, a Figma file, a design brief — turned into a finished film. - -
-
- -
PR to videoA GitHub PR as a reveal · source included
-
-
- -
Figma → HyperFramesA design brought to motion · source included
-
-
- -
Claude DesignFrom a design draft · 100% HyperFrames
-
-
- -
FRAME.md storyboardBrief-driven direction · source included
-
-
- -### Where HyperFrames plugs in - -The same engine, reached from the tools teams already use. Use the player controls to watch and listen. - -
-
- -
Codex pluginHyperFrames inside Codex · 100% HyperFrames
-
-
- -
VercelDeploy from a template · 100% HyperFrames
-
-
- -
Open models (Ollama)Build with local models · 100% HyperFrames
-
-
- -
Community · hyperframes.devPublish and remix · 100% HyperFrames
-
-
+The editing style of popular Reels, TikToks and Shorts, with a different presenter: captions, cutaways, callouts and +pacing. + ## Recreate any video, 1:1 @@ -205,6 +472,6 @@ The init templates remain available for scaffolding complete projects. ## Related topics +- [Reference any video to recreate its style](/studio-app/reference-video) +- [What do you want to make?](/workflows) - [Make your first video](/quickstart) -- [Choose what to make](/workflows) -- [Take more control of an existing project](/studio-app/edit-with-the-agent) diff --git a/docs/snippets/film-rows.jsx b/docs/snippets/film-rows.jsx new file mode 100644 index 0000000000..3ca870ac68 --- /dev/null +++ b/docs/snippets/film-rows.jsx @@ -0,0 +1,196 @@ +/** + * The homepage's showcase on a docs page: two rows of films made with HyperFrames, drifting in opposite directions. + * The card nearest the middle plays its 720p copy, the others show their poster; a click opens the full film with + * sound. Reduced motion holds the rows still on their posters. + */ +export const FilmRows = () => { + // Keep data inside the component: Mintlify compiles only the named export. + const CDN = "https://static.heygen.ai/hyperframes-oss"; + const film = (id, kind, name, ar) => ({ + kind, + name, + ar, + src: `${CDN}/homepage/showcase/card/${id}-v1.mp4`, + hq: `${CDN}/homepage/showcase/hq/${id}-v1.mp4`, + poster: `${CDN}/homepage/showcase/poster/${id}-v1.jpg`, + }); + const launch = `${CDN}/site/studio-launch-nib-sf-audio`; + const rows = [ + [ + { ...film("studio-launch", "Launch film", "Studio launch", 16 / 9), hq: `${launch}.mp4`, poster: `${launch}-poster.jpg` }, + film("vfx-billboard-hoodie-handoff", "VFX", "Out of the billboard", 9 / 16), + film("frameys-opening-night", "Awards trailer", "Opening night", 16 / 9), + film("jake-taycan-bricks", "3D build", "Jake & the Taycan", 1), + film("cartoon-frameys-launch-one-take", "Cartoon", "The Frameys", 16 / 9), + film("k", "Explainer", "The journey of “k”", 9 / 16), + film("real-ui-newspaper-1969", "Real UI", "Men walk on the Moon", 16 / 9), + film("launch-storyboard-first", "Product launch", "Storyboard first", 16 / 9), + film("captions", "Captions", "Don’t tell my clients", 4 / 5), + film("manga-last-onigiri", "Manga", "The last onigiri", 16 / 9), + film("square-one-strudel", "Live-coded music", "Square one", 1), + film("vfx-background-removal-launch", "VFX", "Background removal", 16 / 9), + film("sitcom", "Sitcom", "Two lines", 9 / 16), + film("just-html", "Explainer", "It’s just HTML", 16 / 9), + film("kinetic-type-curiosity", "Kinetic type", "Going through a change", 4 / 3), + film("home", "Many looks", "This homepage", 16 / 9), + film("wordmark-sting", "Logo sting", "Wordmark", 1), + film("session-story", "Cartoon", "Jake’s favorite agent", 16 / 9), + film("launch-claude-motion", "Square", "Claude Motion", 1), + film("real-ui-google-search", "Real UI", "How do cameras focus", 16 / 9), + film("muybridge-horse-styles", "Style study", "One horse, many looks", 32 / 9), + film("rackrats", "Cartoon", "Rackrats", 16 / 9), + ], + [ + film("tutorial-wenbo-studio-tutorial-talkinghead", "Tutorial", "Reference any video", 16 / 9), + film("axe", "3D tutorial", "Axe chop", 9 / 16), + film("framey-orby-halloween", "Cartoon", "Halloween party", 16 / 9), + film("cow", "Launch parody", "Cow 1.0", 16 / 9), + film("ascii-sharks-logo", "Logo sting", "ASCII sharks", 16 / 9), + film("vfx-giant-keyboard-reel", "VFX", "Giant keyboard", 9 / 16), + film("real-ui-wikipedia", "Real UI", "Wikipedia", 16 / 9), + film("launch-heygen-video1", "AI footage", "HeyGen Video 1", 16 / 9), + film("pixel-game-one-canvas", "Code tutorial", "A game in one canvas", 16 / 9), + film("demo", "Talking head", "Tool demo", 9 / 16), + film("everything-was-written", "Motion design", "Everything was written", 16 / 9), + film("launch", "Kinetic type", "Keynote line", 16 / 9), + film("remotion-to-hyperframes", "3D voxel", "Remotion to HyperFrames", 16 / 9), + film("explainer-code2video-bench", "Presenter", "Code2Video Bench", 16 / 9), + film("real-ui-cctv", "Real UI", "CCTV tracking", 16 / 9), + film("frameys-felt-party", "3D characters", "The Frameys dance", 16 / 9), + film("launch-moments-catalog", "Product launch", "Moments catalog", 16 / 9), + film("shards-logo-reveal", "Logo reveal", "Shards", 16 / 9), + film("launch-hyperframes-studio-intro", "Product reveal", "Studio intro", 16 / 9), + film("studio-launch-pixel", "Launch film", "A launch video in 6 hours", 16 / 9), + film("youtube-online-business", "YouTube edit", "Online business story", 16 / 9), + film("website-to-launch", "Product launch", "From your website", 16 / 9), + film("generative-replica", "Generative art", "Code is a material", 16 / 9), + ], + ]; + + const rootRef = useRef(null); + const dialogRef = useRef(null); + const [open, setOpen] = useState(null); + const [paused, setPaused] = useState(false); + // Known on the first render, so nothing loads or moves before the preference is read. + const [still, setStill] = useState( + () => typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches, + ); + + useEffect(() => { + const query = window.matchMedia("(prefers-reduced-motion: reduce)"); + const follow = (event) => setStill(event.matches); + query.addEventListener("change", follow); + return () => query.removeEventListener("change", follow); + }, []); + + // A card loads its file only near the screen, and one plays at a time, the one nearest the middle: with two 720p + // films playing, Chrome drops the whole page from 120 to 30 fps (measured 2026-10-26), drift or not. + useEffect(() => { + const root = rootRef.current; + if (!root) return; + // Reduce Motion turned on mid-visit: stop every film and let go of its file. + if (still) { + for (const v of root.querySelectorAll("video[data-src]")) { + v.pause(); + v.removeAttribute("src"); + v.load(); + } + return; + } + const near = new Set(); + const seen = new IntersectionObserver((entries) => { + for (const { target, isIntersecting } of entries) { + if (isIntersecting) { + if (!target.src) target.src = target.dataset.src; + near.add(target); + } else if (target.src) { + near.delete(target); + target.pause(); + target.removeAttribute("src"); + target.load(); + } + } + }, { rootMargin: "100px" }); + for (const v of root.querySelectorAll("video[data-src]")) seen.observe(v); + const pick = () => { + const mid = window.innerWidth / 2; + const centre = (v) => { const r = v.getBoundingClientRect(); return Math.abs(r.left + r.width / 2 - mid); }; + // Paused rows, or a full film open in the dialog: no preview plays. + // A film playing with sound anywhere on the page (a chosen remix, a replica pair) also rests the previews. + const filmWithSound = [...document.querySelectorAll("video")].some((v) => !v.paused && !v.muted); + const resting = root.classList.contains("is-paused") || root.dataset.watching === "true" || filmWithSound; + const first = resting ? null : [...near].sort((a, b) => centre(a) - centre(b))[0]; + for (const v of near) { + if (v === first) v.play().catch(() => {}); + else v.pause(); + } + }; + const tick = setInterval(pick, 1000); + return () => { seen.disconnect(); clearInterval(tick); }; + }, [still]); + + useEffect(() => { + if (paused) for (const v of rootRef.current?.querySelectorAll("video") ?? []) v.pause(); + }, [paused]); + + // While a full film plays in the dialog, the previews stop, so only one film plays at a time. + useEffect(() => { + const root = rootRef.current; + if (!root) return; + root.dataset.watching = open ? "true" : "false"; + if (open) for (const v of root.querySelectorAll("video[data-src]")) v.pause(); + }, [open]); + + useEffect(() => { + const d = dialogRef.current; + if (!d) return; + if (open && !d.open) d.showModal(); + if (!open && d.open) d.close(); + }, [open]); + + const card = (f, i, twin) => ( + + ); + + return ( +
+ {rows.map((row, r) => ( +
+
+ {row.map((f, i) => card(f, i, false))} + {row.map((f, i) => card(f, i, true))} +
+
+ ))} + {/* WCAG 2.2.2: rows that move on their own get a way to stop them. Reduced motion never moves them, so no button */} + {!still && ( + + )} + setOpen(null)} onClick={(e) => { if (e.target === dialogRef.current) setOpen(null); }}> + {open && ( +
+
+ )} +
+
+ ); +}; diff --git a/docs/snippets/remix-shelf.jsx b/docs/snippets/remix-shelf.jsx new file mode 100644 index 0000000000..fcd3b7dd61 --- /dev/null +++ b/docs/snippets/remix-shelf.jsx @@ -0,0 +1,130 @@ +// A shelf of videos remixed in the Studio app: each card plays HeyGen's remix on hover, credits the original +// (linked to its post), and says how to remix it yourself. Originals are never hosted here. +export const RemixShelf = ({ items, tall = false }) => { + // Hover previews follow the visitor's reduced-motion setting, known on the first render; the film is a button, so + // playing it on purpose works for keyboard and touch, and under reduced motion. + // The setting lives in a ref, not state: a preference change must not re-render the shelf, which would remount + // every card (RemixCard is declared in here, as Mintlify snippets keep helpers inside the export) and lose a + // playing film, focus and open instructions. + const shelfRef = useRef(null); + const reduced = useRef(null); + if (reduced.current === null) + reduced.current = typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches; + useEffect(() => { + const query = window.matchMedia("(prefers-reduced-motion: reduce)"); + const follow = (event) => { + reduced.current = event.matches; + // Turned on mid-visit: stop any hover preview that is running. + if (event.matches) for (const v of shelfRef.current?.querySelectorAll("video") ?? []) if (v.dataset.hover) v.pause(); + }; + query.addEventListener("change", follow); + return () => query.removeEventListener("change", follow); + }, []); + const RemixCard = ({ item }) => { + const videoRef = useRef(null); + const [open, setOpen] = useState(false); + const [copied, setCopied] = useState(false); + const [chosen, setChosen] = useState(false); + // One film at a time across the page: any other video starting with sound (another remix, the full-film dialog, a + // replica pair) is a deliberate choice, so this card stops and lets go of its own. + useEffect(() => { + const onPlay = (event) => { + const v = event.target; + const own = videoRef.current; + if (!(v instanceof HTMLVideoElement) || v.muted || v === own || !own) return; + own.pause(); + own.muted = true; + setChosen(false); + }; + document.addEventListener("play", onPlay, true); + return () => document.removeEventListener("play", onPlay, true); + }, []); + const preview = (on) => { + const v = videoRef.current; + const filmWithSound = [...document.querySelectorAll("video")].some((x) => !x.paused && !x.muted); + if (!v || chosen || (on && filmWithSound)) return; + if (on && !reduced.current) { + v.dataset.hover = "1"; + v.play().catch(() => {}); + } else if (!on) { + delete v.dataset.hover; + v.pause(); + v.currentTime = 0; + } + }; + const toggle = () => { + const v = videoRef.current; + if (!v) return; + // A chosen film plays with its sound; hover previews stay muted. + if (chosen && !v.paused) { + v.pause(); + v.muted = true; + setChosen(false); + } else { + delete v.dataset.hover; + v.muted = false; + v.play().catch(() => {}); + setChosen(true); + } + }; + const copy = async () => { + try { + await navigator.clipboard.writeText(item.post); + setCopied(true); + setTimeout(() => setCopied(false), 1600); + } catch {} + }; + return ( +
+ +
+ {item.name} + + Remix of a video by{" "} + {item.handle} + + + {open && ( +
+ Copy the original's link, then paste it in Reference on the Studio app's Home.{" "} + +
+ )} +
+
+ ); + }; + return ( +
+ {items.map((item) => )} +
+ ); +}; diff --git a/scripts/check-docs-snippet-motion.test.mjs b/scripts/check-docs-snippet-motion.test.mjs index 650f2c2456..7c6bb72ab0 100644 --- a/scripts/check-docs-snippet-motion.test.mjs +++ b/scripts/check-docs-snippet-motion.test.mjs @@ -193,12 +193,8 @@ test("HoverVideo preserves the caller's sizing classes at the Mintlify boundary" assert.match(wrapper[1], /overflow:\s*"hidden"/, "clip the preview inside its card"); }); -test("example films use the catalog player without making its controls source links", () => { - const page = readFileSync(join(here, "../docs/examples.mdx"), "utf8"); +test("the catalog player keeps native controls until the CDN player upgrades it", () => { const source = readFileSync(join(here, "../docs/snippets/example-player.jsx"), "utf8"); - assert.equal((page.match(/]*>\s*