chore: import upstream snapshot with attribution
regression / regression-shards (style-16-prod style-9-prod style-17-prod iframe-render-compat variables-prod mp4-h265-sdr, shard-4) (push) Has been cancelled
regression / regression-shards (style-4-prod style-11-prod style-2-prod animejs-adapter typegpu-adapter parallel-capture-regression, shard-5) (push) Has been cancelled
regression / regression-shards (style-7-prod style-8-prod style-10-prod css-spinner-render-compat webm-transparency mp4-h264-sdr webm-vp9, shard-3) (push) Has been cancelled
regression / regression-shards (sub-composition-video style-18-prod raf-ball-render-compat font-variant-numeric sub-comp-t0 sub-comp-id-selector, shard-7) (push) Has been cancelled
Windows render verification / Detect changes (push) Has been cancelled
Windows render verification / Preflight (lint + format) (push) Has been cancelled
Windows render verification / Render on windows-latest (push) Has been cancelled
Windows render verification / Tests on windows-latest (push) Has been cancelled
CI / Detect changes (push) Has been cancelled
CI / Build (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / Fallow audit (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Typecheck (push) Has been cancelled
CI / Test (push) Has been cancelled
CI / Producer: integration tests (push) Has been cancelled
CI / Producer: unit tests (push) Has been cancelled
CI / File size check (push) Has been cancelled
CI / Test: skills (push) Has been cancelled
CI / Skills: manifest in sync (push) Has been cancelled
CI / CLI: npx shim (macos-latest) (push) Has been cancelled
CI / CLI: npx shim (ubuntu-latest) (push) Has been cancelled
CI / CLI: npx shim (windows-latest) (push) Has been cancelled
CI / SDK: unit + contract + smoke (push) Has been cancelled
CI / Test: runtime contract (push) Has been cancelled
CI / Studio: load smoke (push) Has been cancelled
CI / Smoke: global install (push) Has been cancelled
CI / CLI smoke (required) (push) Has been cancelled
CI / Semantic PR title (push) Has been cancelled
Player perf / Detect changes (push) Has been cancelled
Player perf / Preflight (lint + format) (push) Has been cancelled
Player perf / player-perf (push) Has been cancelled
Player perf / Perf: drift (push) Has been cancelled
Player perf / Perf: fps (push) Has been cancelled
Player perf / Perf: parity (push) Has been cancelled
Player perf / Perf: scrub (push) Has been cancelled
Player perf / Perf: load (push) Has been cancelled
preview-regression / Detect changes (push) Has been cancelled
preview-regression / Preflight (lint + format) (push) Has been cancelled
preview-regression / Preview parity (push) Has been cancelled
preview-regression / preview-regression (push) Has been cancelled
regression / regression (push) Has been cancelled
regression / Detect changes (push) Has been cancelled
regression / Preflight (lint + format) (push) Has been cancelled
regression / regression-shards (hdr-regression style-5-prod style-3-prod mov-prores, shard-1) (push) Has been cancelled
regression / regression-shards (overlay-montage-prod style-12-prod chat missing-host-comp-id png-sequence portrait-edge-bleed, shard-6) (push) Has been cancelled
regression / regression-shards (style-13-prod style-6-prod vignelli-stacking gsap-letters-render-compat audio-mux-parity, shard-8) (push) Has been cancelled
regression / regression-shards (style-15-prod hdr-hlg-regression style-1-prod many-cuts vfr-screen-recording render-symlinked-assets, shard-2) (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Docs / Validate docs (push) Has been cancelled
Sync skills to ClawHub / Publish changed skills (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 12:58:35 +08:00
commit 85453da49f
4031 changed files with 710987 additions and 0 deletions
@@ -0,0 +1,166 @@
# Contributing a Block or Component to the Registry
Guide the user from idea to merged PR for a new registry block or component.
## Workflow
```
1. Clarify → 2. Scaffold → 3. Build → 4. Validate → 5. Preview → 6. Ship
```
### Step 1: Clarify
Ask what they're building. The registry has two item types:
- **Block** (`registry/blocks/`, type `hyperframes:block`) — a full standalone composition with fixed dimensions and duration. Caption styles, VFX effects, title cards, lower thirds.
- **Component** (`registry/components/`, type `hyperframes:component`) — a reusable snippet with no fixed dimensions or duration. CSS effects, text treatments, overlays that adapt to any composition size.
Then ask:
- One-sentence description of the effect
- Visual reference (URL, screenshot, or description)
- Who uses this and when?
### Step 2: Scaffold
Create the registry structure:
**For blocks:**
```
registry/blocks/{block-name}/
{block-name}.html
registry-item.json
```
**For components:**
```
registry/components/{component-name}/
{component-name}.html
registry-item.json
```
**Naming convention:**
| Item name | ID prefix | Example IDs |
| ---------------- | --------- | ---------------------- |
| `cap-hormozi` | `hz` | `hz-cg-0`, `hz-cw-3` |
| `cap-typewriter` | `tw` | `tw-cg-0`, `tw-ch-0-5` |
| `vfx-chrome` | `vc` | `vc-canvas` |
Use a 2-3 letter prefix. ALL element IDs must use this prefix to avoid collisions in sub-compositions.
**registry-item.json** — use the canonical templates in [templates.md](templates.md) (block and component variants, both with all required fields).
### Step 3: Build
Apply the correct template based on type. See [templates.md](templates.md) for copy-paste starters.
#### Caption blocks
**Non-negotiable caption rules:**
- Font: **96px minimum** for proportional fonts. **64-72px acceptable for monospace** (wider characters need less size).
- Readability: `-webkit-text-stroke: 2-3px` OR multi-layer `text-shadow`
- Overflow: call `window.__hyperframes.fitTextFontSize()` on every group
- Karaoke: highlight active word via `tl.to(wordEl, { color/scale }, WORDS[wi].start)`
- Hard kill: `tl.set(groupEl, { opacity: 0, visibility: "hidden" }, g.end)` on EVERY group
- **Never use `tl.from(el, { opacity: 0 })` at the same position as `tl.set(el, { opacity: 1 })`** — the from clobbers the set. Use `tl.to` instead.
**Per-character animation** (typewriter, scramble):
- Wrap each character in `<span>` with ID `{prefix}-ch-{group}-{char}`
- Stagger via `tl.set` at computed intervals from word timestamps
- Cursors/decorative elements: use `tl.set` at intervals — NOT CSS animation (not seekable)
**Positioning variants:**
- Centered: `display: flex; align-items: center; justify-content: center;`
- Lower-third: `position: absolute; bottom: 100px; left: 0; width: 100%; text-align: center;`
- Left-aligned: `position: absolute; bottom: 100px; left: 120px; text-align: left;`
#### VFX blocks (Three.js)
- Use `three@0.147.0` from CDN (global script)
- `tl.eventCallback("onUpdate", renderScene); renderScene();` — NO requestAnimationFrame
- State proxy pattern: GSAP animates plain JS object, render function reads it
- Seeded PRNG (`mulberry32`) for randomness
#### All types
- `data-composition-id` MUST match `window.__timelines["id"]`
- All element IDs prefixed with block abbreviation
- `gsap.timeline({ paused: true })` — always paused
- No `Math.random()`, no `Date.now()`
### Step 4: Validate
```bash
hyperframes lint # 0 errors required
hyperframes check --no-contrast # 0 console errors required
```
### Step 5: Preview
```bash
# Render preview video
hyperframes render -o preview.mp4
# Snapshot for visual QA
hyperframes snapshot --at "1.0,3.0,5.0,7.0"
# Publish to hyperframes.dev for review
npx hyperframes publish
```
**Catalog preview image** — The catalog card uses a PNG at `docs/images/catalog/{kind}/{name}.png` (where `{kind}` is `blocks` or `components`). Generate it from a snapshot, then:
- **HeyGen internal contributors:** run `scripts/upload-docs-images.sh` (requires AWS profile `engineering-767398024897`)
- **External contributors:** attach the preview MP4 to your PR description. A maintainer will generate and upload the catalog image before merging.
### Step 6: Ship
**All steps are required. Missing any one produces a broken catalog entry.**
`{kind}` is `blocks` or `components` depending on what you built in Step 1.
```bash
# 1. Create branch
git checkout -b feat/registry-{name}
# 2. Format HTML
npx oxfmt registry/{kind}/{name}/*.html
# 3. Update registry/registry.json — add entry to the "items" array:
# { "name": "{name}", "type": "hyperframes:block" } (or "hyperframes:component")
# 4. Generate catalog docs page
npx tsx scripts/generate-catalog-pages.ts
# 5. Publish to hyperframes.dev so reviewers can preview
npx hyperframes publish
# 6. Stage everything
git add registry/{kind}/{name}/ registry/registry.json docs/catalog/
# 7. Commit
git commit -m "feat(registry): add {name} — {one sentence}"
# 8. Push and open PR with hyperframes.dev link
git push origin feat/registry-{name}
gh pr create --title "feat(registry): {name}" --body "preview: {hyperframes.dev-url}"
```
**If you don't have a GitHub account:** you need one to open a PR. Sign up at https://github.com/signup, then run `gh auth login`.
## Quality Gate
- [ ] `hyperframes lint` → 0 errors
- [ ] `hyperframes check` → 0 console errors
- [ ] `npx oxfmt --check` passes
- [ ] `registry/registry.json` updated with new entry
- [ ] `scripts/generate-catalog-pages.ts` run (docs page generated)
- [ ] `npx hyperframes publish` run (claim your project URL)
- [ ] Preview MP4 attached to PR (external) or catalog PNG uploaded (internal)
- [ ] All IDs unique and prefixed
@@ -0,0 +1,54 @@
# The demo.html Convention
## Why components ship demo.html
Every component in the registry ships a companion `demo.html` file alongside its snippet. The demo serves two purposes:
1. **Preview fixture** — the CI preview pipeline renders the demo to generate thumbnail images and preview videos for the catalog docs page.
2. **Usage example** — the demo shows the component effect applied to representative content, serving as a working reference.
## Demo structure
A demo is a complete, standalone HTML composition:
```html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=1920, height=1080" />
<title>Component Name — Demo</title>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
<style>
/* reset + canvas size */
</style>
</head>
<body>
<div data-composition-id="<name>-demo" data-width="1920" data-height="1080" data-duration="N">
<!-- Demo content showing the effect -->
<!-- Component snippet inlined here -->
</div>
<script>
// GSAP timeline demonstrating the effect
window.__timelines = window.__timelines || {};
window.__timelines["<name>-demo"] = tl;
</script>
</body>
</html>
```
Key conventions:
- `data-composition-id` is `<component-name>-demo` to avoid collisions
- The demo is self-contained — all CSS and JS from the snippet is inlined
- The GSAP timeline is registered on `window.__timelines`
- Duration should be long enough to showcase the effect (typically 5-8 seconds)
## Blocks don't need demo.html
Blocks are already standalone compositions that can be rendered directly. Only components need the demo wrapper.
## Demos are not installed
The `demo.html` is NOT installed by `hyperframes add` — it exists only in the registry for preview generation and as a reference.
@@ -0,0 +1,215 @@
# Registry Discovery
## Reading the registry manifest
The top-level `registry.json` lists all available items:
```bash
curl -s https://raw.githubusercontent.com/heygen-com/hyperframes/main/registry/registry.json
```
Each entry has `name` and `type` (`hyperframes:example`, `hyperframes:block`, or `hyperframes:component`).
## Reading an item's manifest
Each item has a `registry-item.json` with full metadata:
```
<base>/<type-dir>/<name>/registry-item.json
```
Where `<type-dir>` is `examples`, `blocks`, or `components`.
## Item manifest fields
| Field | Type | Required | Description |
| ---------------------- | -------- | -------- | ---------------------------------------------- |
| `name` | string | yes | Kebab-case identifier |
| `type` | string | yes | `hyperframes:block` or `hyperframes:component` |
| `title` | string | yes | Human-readable title |
| `description` | string | yes | One-line description |
| `tags` | string[] | no | Filter tags (e.g., `["data", "chart"]`) |
| `dimensions` | object | blocks | `{ width, height }` — blocks only |
| `duration` | number | blocks | Duration in seconds — blocks only |
| `files` | array | yes | Files to install (`path`, `target`, `type`) |
| `registryDependencies` | string[] | no | Other registry items this depends on |
## Available items
### Blocks
For an always-current list run `npx hyperframes catalog --type block`. The tables below group the 97 blocks by category. **Block name ≠ shader name**: shader-transition blocks (e.g. `domain-warp-dissolve`) wrap a HyperShader runtime whose internal name omits the `-dissolve`/`-warp` suffix — see the showcase HTML installed alongside the block for the canonical name.
#### Shader transitions (14)
Single-shader blocks; each installs one HyperShader runtime + a showcase composition. Use ≤2 per video.
| Name | Description |
| ------------------------ | ------------------------------------------------------------------------ |
| `chromatic-radial-split` | Chromatic aberration radial split |
| `cinematic-zoom` | Dramatic zoom blur |
| `cross-warp-morph` | Cross-warped morphing |
| `domain-warp-dissolve` | Fractal noise domain warping |
| `flash-through-white` | White flash crossfade (rarely a neutral default — see SKILL.md guidance) |
| `glitch` | Digital glitch artifacts |
| `gravitational-lens` | Gravitational lensing distortion |
| `light-leak` | Cinematic light leak overlay |
| `ridged-burn` | Ridged turbulence burn |
| `ripple-waves` | Concentric ripple wave distortion |
| `sdf-iris` | Signed-distance-field iris reveal |
| `swirl-vortex` | Swirling vortex distortion |
| `thermal-distortion` | Heat-haze thermal distortion |
| `whip-pan` | Fast camera whip-pan |
#### Transition galleries (13)
Showcase compositions grouping multiple CSS / GSAP transition styles by family. Use as reference for picking a CSS scene transition; not meant to embed as-is.
| Name | Description |
| ------------------------- | ----------------------------------- |
| `transitions-3d` | 3D perspective flip and rotate |
| `transitions-blur` | Blur-based scene transitions |
| `transitions-cover` | Cover / uncover slide |
| `transitions-destruction` | Destructive break-apart |
| `transitions-dissolve` | Dissolve and fade |
| `transitions-distortion` | Warp and distortion |
| `transitions-grid` | Grid-based tile |
| `transitions-light` | Light-based glow and flash |
| `transitions-mechanical` | Mechanical shutter and iris |
| `transitions-other` | Misc creative (VHS, gravity, morph) |
| `transitions-push` | Push and slide |
| `transitions-radial` | Radial wipe and reveal |
| `transitions-scale` | Scale and zoom |
#### Liquid Glass (7)
WebGPU + html-in-canvas frosted-glass surfaces. **Require Brave / Chrome canary** with WebGPU enabled — set `PRODUCER_HEADLESS_SHELL_PATH` to point at the browser; engine auto-passes `--enable-unsafe-webgpu`. See `/hyperframes-animation``adapters/typegpu.md`.
| Name | Description |
| ----------------------------- | --------------------------------------------------------------------------------------- |
| `ios26-liquid-glass` | 3D iPhone (GLTF) + iOS 26 home screen, glass app icons, shader wallpaper, notifications |
| `macos-tahoe-liquid-glass` | 3D MacBook (GLTF) + macOS Tahoe-style desktop, glass menu bar, Finder, dock |
| `liquid-glass-widgets` | Frosted stat cards, showcase panel, pill chips over aurora shader |
| `liquid-glass-notification` | Frosted notification cards floating over aurora shader |
| `liquid-glass-context-menu` | Frosted context-menu panel drifting over aurora shader |
| `liquid-glass-media-controls` | Frosted media-control panels spreading over aurora shader |
| `vfx-liquid-glass` | Bare VFX composition shell for liquid-glass effects |
#### VFX (6)
HTML-in-canvas + WebGL composition blocks. See `/hyperframes-animation``adapters/three.md` and `adapters/html-in-canvas-patterns.md` for the underlying APIs.
| Name | Description |
| ----------------------- | ------------------------------------------------------------------------------------------------------- |
| `vfx-iphone-device` | GLTF iPhone 15 Pro Max + MacBook Pro with live HTML-in-canvas screens, glass-lens morph, 360° turntable |
| `vfx-liquid-background` | Organic liquid sim — vertex displacement on subdivided plane, HTML floats above |
| `vfx-magnetic` | VFX shell (magnetic field-line treatment) |
| `vfx-portal` | VFX shell (portal reveal) |
| `vfx-shatter` | VFX shell (shatter into fragments) |
| `vfx-text-cursor` | Cursor glow + chromatic shadow rays + spectral edges on a black stage |
#### Showcases (6)
Story-driven showcase compositions — narrated YouTube-style inserts. Most include bundled SFX.
| Name | Description |
| -------------------------- | ----------------------------------------------------------------- |
| `app-showcase` | Three floating smartphone screens, fitness app product showcase |
| `apple-money-count` | Counter $0 → $10,000, green flash, money-icon burst, SFX |
| `blue-sweater-intro-video` | Warm AI-creator intro resolving into an X follow card |
| `north-korea-locked-down` | Map zoom with red scribble circle, locked-down pop-up label |
| `nyc-paris-flight` | Map animation, plane NYC → Paris, marker circle, landing pop, SFX |
| `vpn-youtube-spot` | App-store scroll, VPN install flow, SFX |
#### Maps + data viz (8)
D3 + GSAP animated geographies and charts.
| Name | Description |
| ---------------------------------- | -------------------------------------------------------------------------------------------------- |
| `us-map` | US choropleth, staggered state reveals, value labels, gradient legend |
| `us-map-bubble` | US bubble map — proportional city markers, callouts, connection lines |
| `us-map-flow` | US flow map — animated origin-destination arcs |
| `us-map-hex` | US hex-grid map — each state as equal-weight hex with data fill |
| `spain-map` | Spain choropleth by autonomous community — D3 conic conformal |
| `world-map` | World choropleth + rotating globe inset, D3 Natural Earth |
| `data-chart` | Animated bar + line chart, staggered reveal, NYT-style typography |
| `flowchart` / `flowchart-vertical` | Decision tree, SVG connectors, sticky-note nodes, cursor + typing correction (vertical = portrait) |
#### Social overlays (7)
Platform-recognizable UI overlays. Stamp on top of a beat or use as a beat closer.
| Name | Description |
| -------------------- | ------------------------------------------------ |
| `instagram-follow` | Profile card + follow button |
| `tiktok-follow` | Profile card + follow button |
| `yt-lower-third` | YouTube subscribe lower third with avatar |
| `x-post` | X/Twitter post card with engagement metrics |
| `reddit-post` | Post card with upvotes and comments |
| `spotify-card` | Now-playing card with album art and progress bar |
| `macos-notification` | macOS-style banner with app icon and message |
#### Branding + 3D UI (2)
| Name | Description |
| -------------- | ------------------------------------------------------------------- |
| `logo-outro` | Piece-by-piece logo assembly, glow bloom, tagline fade-in, URL pill |
| `ui-3d-reveal` | Perspective 3D reveal for UI elements |
#### Code snippets (24)
A code/terminal window that **types a code or shell session per-character**. Theme = visual chrome only; structure, wiring, and install are identical across all 24 — pick one by name, wire it like any block (`data-composition-id` + `data-start` + `data-track-index`, see `wiring-blocks.md`). Two chrome families:
**VS Code workbench (12)** — full editor chrome (activity bar, sidebar, tabs, integrated terminal, status bar). Theme variants: `code-snippet-dark-2026`, `code-snippet-dark-modern`, `code-snippet-dark-plus`, `code-snippet-light-2026`, `code-snippet-light-modern`, `code-snippet-light-plus`, `code-snippet-high-contrast`, `code-snippet-high-contrast-light`, `code-snippet-monokai`, `code-snippet-solarized-light`, `code-snippet-visual-studio-dark`, `code-snippet-visual-studio-light`.
**Apple Terminal (12)** — macOS Terminal.app window typing a shell session. Profile = window colors:
| Name | Look |
| -------------------------------------------- | ---------------------------------------- |
| `code-snippet-apple-terminal-basic` | White bg, black text |
| `code-snippet-apple-terminal-clear-dark` | Semi-transparent dark bg |
| `code-snippet-apple-terminal-clear-light` | Semi-transparent light bg |
| `code-snippet-apple-terminal-grass` | Black bg, green text |
| `code-snippet-apple-terminal-homebrew` | Black bg, bright green text, lime cursor |
| `code-snippet-apple-terminal-man-page` | Pale yellow bg, black text |
| `code-snippet-apple-terminal-novel` | Warm parchment bg, dark brown text |
| `code-snippet-apple-terminal-ocean` | Deep blue bg, white text |
| `code-snippet-apple-terminal-pro` | Black bg, grey text, lime cursor |
| `code-snippet-apple-terminal-red-sands` | Deep red bg, sandy text |
| `code-snippet-apple-terminal-silver-aerogel` | Dark grey bg, white text |
| `code-snippet-apple-terminal-solid-colors` | Deep purple bg, white text |
#### Code Animations (9)
The richer, motion-first counterpart to the static `code-snippet-*` window themes above: each is a self-contained 1920×1080 block (~58s) with a paused, deterministic GSAP timeline that _animates_ code — typing, diffing, morphing, spotlighting, or GPU hero reveals — rather than typing a fixed snippet inside editor/terminal chrome. **Reuse-first**: `npx hyperframes add <name>`, then customize the baked code/diff content in place; hand-author only when no block covers the motion you need.
**DOM / text reveal (6):**
| Name | Description |
| --------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `code-typing` | Token-streamed typing reveal, caret tracks the frontier (no CSS animation) — live-coding on screen |
| `code-diff` | An edit shown as a colored diff: removed lines collapse red, added expand green — before/after at line level |
| `code-morph` | One snippet transforms into another, tokens glide between positions (Shiki Magic Move) — a refactor / one state to another |
| `code-highlight` | A highlight band sweeps a target line while surrounding context dims — spotlight one line |
| `code-scroll` | Camera scrolls a long file to center + spotlight a target line — walk through a real module |
| `code-snippet-flight` | Discrete snippets fly in from the side and assemble into a stacked program (block-level FLIP) |
**GPU / WebGL hero reveals (3):** heavier, for a title-card / hero code moment.
| Name | Description |
| ------------------------ | --------------------------------------------------------------------------------------------------------------- |
| `code-3d-extrude` | Syntax-highlighted code on a lit beveled 3D slab that rotates through real space and settles (true WebGL depth) |
| `code-shader-dissolve` | Code resolves out of seeded noise with a chromatic dissolve front + edge glow, then holds crisp |
| `code-particle-assemble` | Thousands of GPU points fly to the exact glyph pixels and resolve into readable syntax-highlighted code |
### Components
| Name | Description | Tags |
| -------------------- | --------------------------------------------------------------------------------------------------------- | ------------------------------------------------ |
| `grain-overlay` | Animated film grain texture overlay | texture, grain, overlay, film |
| `shimmer-sweep` | CSS gradient light sweep for AI accents | text, shimmer, highlight, effect |
| `morph-text` | Gooey text morph cycling an editable word list (SVG threshold + GSAP blur) | text, text-effect, typography, morph, gooey |
| `grid-pixelate-wipe` | Grid dissolve transition between scenes | transition, wipe, grid, pixelate |
| `parallax-zoom` | Center card scales up to fill the frame while siblings parallax outward (single `--pz-progress` 0→1) | transition, zoom, parallax, grid, hero |
| `parallax-unzoom` | Reverse of `parallax-zoom` — focus card shrinks from full frame as siblings parallax in (`--pu-progress`) | transition, reveal, unzoom, parallax, grid, hero |
@@ -0,0 +1,45 @@
# Install Locations
## Default paths
| Item type | Default install path | Configured by |
| --------- | ------------------------------------- | ----------------------------------- |
| Block | `compositions/<name>.html` | `hyperframes.json#paths.blocks` |
| Component | `compositions/components/<name>.html` | `hyperframes.json#paths.components` |
## How path remapping works
The `target` field in each item's `registry-item.json` specifies a default install path. The `add` command remaps the prefix based on `hyperframes.json#paths`:
- Block targets starting with `compositions/` get remapped to `<paths.blocks>/`
- Component targets starting with `compositions/components/` get remapped to `<paths.components>/`
## hyperframes.json
Created automatically by `hyperframes init`. If it doesn't exist when you run `add`, the CLI creates it with defaults:
```json
{
"$schema": "https://hyperframes.heygen.com/schema/hyperframes.json",
"registry": "https://raw.githubusercontent.com/heygen-com/hyperframes/main/registry",
"paths": {
"blocks": "compositions",
"components": "compositions/components",
"assets": "assets"
}
}
```
## Custom layouts
To install blocks into a `scenes/` directory instead of `compositions/`:
```json
{
"paths": {
"blocks": "scenes"
}
}
```
Then `hyperframes add data-chart` writes to `scenes/data-chart.html` instead of `compositions/data-chart.html`. The snippet output reflects the remapped path.
@@ -0,0 +1,417 @@
# Contribute Templates
Copy-paste starter templates for each component type. These embed the proven patterns that pass lint and validate.
## Caption Template
```html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link
href="https://fonts.googleapis.com/css2?family=Montserrat:wght@800;900&display=swap"
rel="stylesheet"
/>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
<style>
*,
*::before,
*::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background: #111;
overflow: hidden;
}
#root-BLOCKNAME {
position: relative;
width: 1920px;
height: 1080px;
overflow: hidden;
background: #111;
}
.cap-container {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
.cg {
position: absolute;
display: flex;
align-items: center;
justify-content: center;
gap: 32px;
max-width: 1700px;
overflow: visible;
opacity: 0;
visibility: hidden;
}
.cw {
font-family: "Montserrat", sans-serif;
font-weight: 900;
font-size: 128px;
color: #ffffff;
text-transform: uppercase;
line-height: 1;
display: inline-block;
-webkit-text-stroke: 3px rgba(0, 0, 0, 0.8);
paint-order: stroke fill;
text-shadow: 0 4px 12px rgba(0, 0, 0, 0.5);
}
</style>
</head>
<body>
<div
id="root-BLOCKNAME"
data-composition-id="BLOCKNAME"
data-start="0"
data-duration="9"
data-width="1920"
data-height="1080"
>
<div class="cap-container" id="cc-BLOCKNAME"></div>
<div
id="drv-BLOCKNAME"
class="clip"
data-start="0"
data-duration="9"
data-track-index="0"
style="position:absolute;width:1px;height:1px;opacity:0;pointer-events:none"
></div>
</div>
<script>
(function () {
window.__timelines = window.__timelines || {};
// REPLACE with actual transcript data
var WORDS = [
{ text: "Welcome", start: 0.3, end: 0.65 },
{ text: "to", start: 0.65, end: 0.8 },
{ text: "the", start: 0.8, end: 0.95 },
{ text: "future", start: 0.95, end: 1.4 },
// ... add all words
];
var GROUPS = [
{ start: 0.3, end: 1.3, wordStart: 0, wordEnd: 3, text: "Welcome to the future" },
// ... add all groups
];
var container = document.getElementById("cc-BLOCKNAME");
GROUPS.forEach(function (g, gi) {
var groupEl = document.createElement("div");
groupEl.id = "PREFIX-cg-" + gi;
groupEl.className = "cg";
for (var wi = g.wordStart; wi <= g.wordEnd; wi++) {
var wordEl = document.createElement("span");
wordEl.id = "PREFIX-cw-" + wi;
wordEl.className = "cw";
wordEl.textContent = WORDS[wi].text;
groupEl.appendChild(wordEl);
}
// Pretext overflow prevention
if (window.__hyperframes && window.__hyperframes.fitTextFontSize) {
var _fit = window.__hyperframes.fitTextFontSize(g.text.toUpperCase(), {
fontFamily: "Montserrat",
fontWeight: 900,
maxWidth: 1550,
baseFontSize: 128,
minFontSize: 48,
});
if (_fit.fontSize < 128) {
for (var _fi = 0; _fi < groupEl.children.length; _fi++) {
groupEl.children[_fi].style.fontSize = _fit.fontSize + "px";
}
}
}
container.appendChild(groupEl);
});
var tl = gsap.timeline({ paused: true });
GROUPS.forEach(function (g, gi) {
var groupEl = document.getElementById("PREFIX-cg-" + gi);
// SHOW — set opacity to 1 (never use tl.from with opacity:0 here)
tl.set(groupEl, { opacity: 1, visibility: "visible" }, g.start);
// ENTRANCE — customize this per style
tl.from(groupEl, { scale: 1.3, duration: 0.15, ease: "back.out(2)" }, g.start);
// KARAOKE — highlight each word
for (var wi = g.wordStart; wi <= g.wordEnd; wi++) {
var wordEl = document.getElementById("PREFIX-cw-" + wi);
tl.to(wordEl, { color: "#FFD700", scale: 1.1, duration: 0.06 }, WORDS[wi].start);
tl.to(wordEl, { color: "#FFFFFF", scale: 1, duration: 0.08 }, WORDS[wi].end);
}
// EXIT
tl.to(groupEl, { opacity: 0, scale: 0.9, duration: 0.1 }, g.end - 0.1);
// HARD KILL (mandatory)
tl.set(groupEl, { opacity: 0, visibility: "hidden" }, g.end);
});
window.__timelines["BLOCKNAME"] = tl;
})();
</script>
</body>
</html>
```
**Replace checklist:**
- `BLOCKNAME` → your block name (e.g., `cap-swoosh`)
- `PREFIX` → short unique prefix for IDs (e.g., `sw`)
- Font family, weight, size → your style's typography
- Entrance animation → your style's entrance
- Karaoke highlight → your style's active word treatment
- Colors → your style's palette
---
## VFX Template
```html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.147.0/build/three.min.js"></script>
<style>
*,
*::before,
*::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background: #030308;
overflow: hidden;
}
#root-BLOCKNAME {
position: relative;
width: 1920px;
height: 1080px;
overflow: hidden;
background: #030308;
}
#canvas-BLOCKNAME {
position: absolute;
top: 0;
left: 0;
width: 1920px;
height: 1080px;
}
</style>
</head>
<body>
<div
id="root-BLOCKNAME"
data-composition-id="BLOCKNAME"
data-start="0"
data-duration="10"
data-width="1920"
data-height="1080"
>
<canvas id="canvas-BLOCKNAME" width="1920" height="1080"></canvas>
<div
id="drv-BLOCKNAME"
class="clip"
data-start="0"
data-duration="10"
data-track-index="0"
style="position:absolute;width:1px;height:1px;opacity:0;pointer-events:none"
></div>
</div>
<script>
(function () {
window.__timelines = window.__timelines || {};
// Seeded PRNG — NEVER use Math.random()
function mulberry32(a) {
return function () {
a |= 0;
a = (a + 0x6d2b79f5) | 0;
var t = Math.imul(a ^ (a >>> 15), 1 | a);
t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;
return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
};
}
var rng = mulberry32(42);
var W = 1920,
H = 1080;
var canvas = document.getElementById("canvas-BLOCKNAME");
var renderer = new THREE.WebGLRenderer({ canvas: canvas, antialias: true });
renderer.setSize(W, H);
renderer.setPixelRatio(1);
renderer.toneMapping = THREE.ACESFilmicToneMapping;
renderer.toneMappingExposure = 1.1;
var scene = new THREE.Scene();
scene.background = new THREE.Color(0x030308);
var camera = new THREE.PerspectiveCamera(50, W / H, 0.1, 100);
camera.position.set(0, 0, 8);
// YOUR SCENE SETUP HERE
// - lights
// - geometry
// - materials
// State proxy — GSAP animates this, render reads it
var st = {
rotY: 0,
camZ: 8,
// add your animated properties
};
var tl = gsap.timeline({ paused: true });
// YOUR TWEENS HERE
tl.to(st, { rotY: Math.PI * 2, duration: 10, ease: "none" }, 0);
window.__timelines["BLOCKNAME"] = tl;
function renderScene() {
// Apply state to Three.js objects
camera.position.z = st.camZ;
// mesh.rotation.y = st.rotY;
renderer.render(scene, camera);
}
// Render via onUpdate — NO requestAnimationFrame
tl.eventCallback("onUpdate", renderScene);
renderScene();
})();
</script>
</body>
</html>
```
**Replace checklist:**
- `BLOCKNAME` → your block name (e.g., `vfx-chrome-blob`)
- Scene setup → your geometry, lights, materials
- State proxy → your animated properties
- Tweens → your animation timeline
- renderScene → apply state to your Three.js objects
---
## registry-item.json Templates
**For blocks:**
```json
{
"$schema": "https://hyperframes.heygen.com/schema/registry-item.json",
"name": "BLOCKNAME",
"type": "hyperframes:block",
"title": "Human-Readable Title",
"description": "One sentence: what it does and who uses it",
"dimensions": { "width": 1920, "height": 1080 },
"duration": 10,
"tags": ["category", "subcategory"],
"files": [
{
"path": "BLOCKNAME.html",
"target": "compositions/BLOCKNAME.html",
"type": "hyperframes:composition"
}
]
}
```
**For components** (no `dimensions` or `duration`):
```json
{
"$schema": "https://hyperframes.heygen.com/schema/registry-item.json",
"name": "COMPONENTNAME",
"type": "hyperframes:component",
"title": "Human-Readable Title",
"description": "One sentence: what it does",
"tags": ["category"],
"files": [
{
"path": "COMPONENTNAME.html",
"target": "compositions/components/COMPONENTNAME.html",
"type": "hyperframes:snippet"
}
]
}
```
Tags by category:
- Captions: `captions`, `viral`, `professional`, `karaoke`, `minimal`
- VFX: `three-js`, `particles`, `shader`, `gpu`
- Transitions: `transition`, `shader`, `wipe`, `dissolve`
- Blocks: `lower-third`, `social`, `title-card`, `data-viz`
- Components: `effect`, `overlay`, `text-treatment`
---
## Component Template
```html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
<style>
*,
*::before,
*::after {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background: transparent;
overflow: hidden;
}
.COMPNAME-wrap {
position: absolute;
inset: 0;
overflow: hidden;
pointer-events: none;
}
</style>
</head>
<body>
<div class="COMPNAME-wrap">
<!-- Your reusable effect/overlay here -->
</div>
<script>
(function () {
// Component snippet — no data-composition-id, no __timelines.
// The parent composition controls timing.
// Keep all class names and IDs prefixed with COMPNAME.
})();
</script>
</body>
</html>
```
**Replace checklist:**
- `COMPNAME` → your component name (e.g., `shimmer-sweep`)
- Background should be `transparent` so it overlays cleanly
- No `data-composition-id` or `window.__timelines` — the parent owns timing
@@ -0,0 +1,61 @@
# Wiring Blocks
Blocks are standalone compositions with their own `data-composition-id`, dimensions, duration, and GSAP timeline. Include them in a host composition using `data-composition-src` on a `<div>`.
## Basic wiring
After `hyperframes add data-chart`, wire it into your `index.html`:
```html
<div id="stage" data-composition-id="main" data-width="1920" data-height="1080" data-duration="20">
<video id="a-roll" src="video.mp4" data-start="0" data-duration="20" data-track-index="0"></video>
<!-- Block: appears at 2s, plays for 15s, on layer 1 -->
<div
data-composition-id="data-chart"
data-composition-src="compositions/data-chart.html"
data-start="2"
data-duration="15"
data-track-index="1"
data-width="1920"
data-height="1080"
></div>
</div>
```
## Required attributes
| Attribute | Description |
| ---------------------- | -------------------------------------------------------------------- |
| `data-composition-src` | Path to the block HTML file (relative to index.html) |
| `data-composition-id` | Unique ID matching the block's internal composition ID |
| `data-start` | When the block appears in the host timeline (seconds) |
| `data-duration` | How long the block plays (seconds, at most the block's own duration) |
| `data-track-index` | Layer ordering — higher numbers render in front |
| `data-width` | Block canvas width (match the block's dimensions) |
| `data-height` | Block canvas height (match the block's dimensions) |
## Timeline coordination
The block's internal GSAP timeline runs independently from the host timeline. The HyperFrames runtime loads the sub-composition, finds its `window.__timelines` registration, and seeks the block in sync with the host, offset by `data-start`. You do NOT need to reference the block's timeline in your host's GSAP code.
## Positioning blocks
To position a block in a specific area of the screen, add CSS:
```html
<div
data-composition-id="data-chart"
data-composition-src="compositions/data-chart.html"
data-start="2"
data-duration="15"
data-track-index="1"
data-width="1920"
data-height="1080"
style="position: absolute; right: 0; top: 0; width: 40%; height: 100%;"
></div>
```
## Multiple blocks
Add additional `<div data-composition-src="...">` siblings with non-overlapping or overlapping `data-start` values — each block's timeline is independent and seeked in sync by the runtime.
@@ -0,0 +1,39 @@
# Wiring Components
Components are effect snippets — HTML, CSS, and optionally JS that you merge directly into an existing composition. Unlike blocks, components have no standalone timeline; they participate in the host composition's timeline.
## General process
1. Run `hyperframes add <component-name>`
2. Open the installed file (e.g., `compositions/components/grain-overlay.html`)
3. Read the comment header for usage instructions
4. Copy the parts into your host composition:
- **HTML elements** — inside your `<div data-composition-id="...">`
- **CSS styles** — into your composition's `<style>` block
- **JS setup** — into your composition's `<script>`, before your timeline code
- **Timeline calls** — into your GSAP timeline (if the component exposes them)
## Example: grain-overlay (CSS-only, no timeline integration)
```html
<!-- Paste the overlay div into your composition -->
<div
id="grain-overlay"
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; pointer-events: none; z-index: 100;"
>
<div class="grain-texture"></div>
</div>
```
Then paste the CSS keyframes and `.grain-texture` rule into your styles. No GSAP timeline calls needed — the grain animates via CSS `@keyframes`.
## Example: shimmer-sweep (needs timeline integration)
See `examples/add-component.md` for the full shimmer-sweep walkthrough (HTML wrapping, CSS, JS setup, and timeline call).
## Key principles
- Components inherit the host composition's dimensions and duration
- Place component HTML at the appropriate z-index relative to your content
- Read the comment header in each snippet for customizable values
- Run `hyperframes lint` after wiring to catch structural issues