mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-01 19:42:03 +00:00
## What PR 5/17 of the catalog system rollout. Adds the `hyperframes add` verb for installing blocks and components from the registry into an existing project, plus the `hyperframes.json` project config that tells `add` which registry to use and where to drop files. Stacks on #255. - **`packages/cli/src/commands/add.ts`** — new `hyperframes add <name>` command. Resolves an item, validates target paths, installs files in parallel, builds an include snippet, copies it to the clipboard. Exposes a testable `runAdd(opts)` function; the citty default wraps it with console output + exit handling - **`packages/cli/src/utils/projectConfig.ts`** — read/write/normalize `hyperframes.json`. Tolerant to missing and partial configs - **`packages/cli/src/utils/clipboard.ts`** — minimal cross-platform clipboard (pbcopy / clip.exe / wl-copy / xclip / xsel). Zero deps. Gracefully no-ops in headless environments - **`packages/cli/src/commands/init.ts`** — write `hyperframes.json` during scaffold if not already present - **`packages/cli/src/cli.ts`** + **`help.ts`** — register `add` under Getting Started (directly below `init`) Design doc: [Hyperframes Catalog System](https://www.notion.so/heygen/Hyperframes-Catalog-System-Design-Plan-341449792c69813f899dcd53b4c0383a). ## UX ```bash # Scaffold a project (now writes hyperframes.json too) npx hyperframes init my-video --example blank cd my-video # Add a block — files land, snippet copied to clipboard npx hyperframes add claude-code-window # ✓ Added claude-code-window (hyperframes:block) # compositions/claude-code-window.html # # Include snippet: # <iframe src="compositions/claude-code-window.html" data-start="0" data-duration="6"></iframe> # # Copied to clipboard — paste into your host composition. # Add a component effect npx hyperframes add shader-wipe # Headless / CI — no clipboard, JSON output for tooling npx hyperframes add shader-wipe --no-clipboard --json ``` Running `hyperframes add warm-grain` (an example) errors clearly pointing to `init --example`. ## Docs (bundled in this PR per the tracker principle) - `docs/packages/cli.mdx` — new `add` subsection under Commands (flags, examples, trigger rules) + new `hyperframes.json` section describing the config file shape ## Tests - **`packages/cli/src/commands/add.test.ts`** — 11 tests: - `remapTarget` / `buildSnippet` pure helpers (5 tests) - `runAdd` integration against a mocked `fetch` registry: block install lands files + returns snippet, component install respects `paths.components` remap, example-typed names throw `AddError` with code `example-type`, unknown names throw `AddError` with code `unknown-item` (4 tests plus 2 covering block default path and non-default path preservation) - **`packages/cli/src/utils/projectConfig.test.ts`** — 9 tests: - Write/read round-trip, partial-config normalization, corrupt-file handling, absent-file fallback to defaults, custom paths preserved - **CLI suite:** 92 passed (was 72 on #255, **+20**). Same 4 pre-existing failures unchanged ## Scope decisions - **`init.ts` full port to new resolver deferred.** The original plan bundled a removal of the `packages/cli/src/templates/` compat shim. That's ~300 more lines and isn't required for `add` to work. The compat shim from #254 still functions; a separate cleanup PR handles it - **No ajv runtime schema validation.** Manifests are trusted as schema-valid. Full validation lands when third-party registries arrive (PR 14/15). Path safety is still enforced by the installer's `assertSafeTarget` guard - **Default project paths stay under `compositions/`.** Blocks → `compositions/<name>.html`; components → `compositions/components/<name>/<file>`. Users override via `hyperframes.json#paths` ## Breaking / migration **None.** Pure additive — new command, new file types, no existing commands or flags change. `init.ts` now writes `hyperframes.json` but that's a new additional file, not a modification of existing output. ## Stacks on #255 — base branch. When #255 merges, this rebases onto `main`. ## Next in stack PR 6 — `feat(registry): seed block — claude-code-window`. First real registry item. Exercises the full `hyperframes add <name>` flow end-to-end against a committed item on `main`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
271 lines
11 KiB
Plaintext
271 lines
11 KiB
Plaintext
---
|
||
title: Examples
|
||
description: "Built-in examples for common video patterns. Hover to preview animations."
|
||
---
|
||
|
||
Hyperframes includes starter examples to help you scaffold compositions quickly. Each example gives you a working project with the correct [composition structure](/concepts/compositions), [data attributes](/concepts/data-attributes), and a [GSAP timeline](/guides/gsap-animation) already wired up.
|
||
|
||
```bash Terminal
|
||
npx hyperframes init my-video --example <name>
|
||
```
|
||
|
||
## Landscape Templates
|
||
|
||
<div className="not-prose grid grid-cols-2 gap-4 my-6">
|
||
<div className="tpl-card relative rounded-xl overflow-hidden bg-zinc-900 transition-transform hover:-translate-y-0.5 hover:shadow-xl">
|
||
<video className="w-full aspect-video object-cover block" src="/images/templates/warm-grain.mp4" poster="/images/templates/warm-grain.png" muted loop playsInline preload="metadata" />
|
||
<div className="absolute bottom-0 left-0 right-0 pt-6 pb-2 px-3" style={{background: "linear-gradient(transparent, rgba(0,0,0,0.7))"}}><strong className="text-sm font-semibold text-white block">Warm Grain</strong><span className="text-xs text-zinc-300">Branding & lifestyle</span></div>
|
||
</div>
|
||
<div className="tpl-card relative rounded-xl overflow-hidden bg-zinc-900 transition-transform hover:-translate-y-0.5 hover:shadow-xl">
|
||
<video className="w-full aspect-video object-cover block" src="/images/templates/play-mode.mp4" poster="/images/templates/play-mode.png" muted loop playsInline preload="metadata" />
|
||
<div className="absolute bottom-0 left-0 right-0 pt-6 pb-2 px-3" style={{background: "linear-gradient(transparent, rgba(0,0,0,0.75))"}}><strong className="text-sm font-semibold text-white block">Play Mode</strong><span className="text-xs text-zinc-300">Social media</span></div>
|
||
</div>
|
||
<div className="tpl-card relative rounded-xl overflow-hidden bg-zinc-900 transition-transform hover:-translate-y-0.5 hover:shadow-xl">
|
||
<video className="w-full aspect-video object-cover block" src="/images/templates/swiss-grid.mp4" poster="/images/templates/swiss-grid.png" muted loop playsInline preload="metadata" />
|
||
<div className="absolute bottom-0 left-0 right-0 pt-6 pb-2 px-3" style={{background: "linear-gradient(transparent, rgba(0,0,0,0.75))"}}><strong className="text-sm font-semibold text-white block">Swiss Grid</strong><span className="text-xs text-zinc-300">Corporate & technical</span></div>
|
||
</div>
|
||
<div className="tpl-card relative rounded-xl overflow-hidden bg-zinc-900 transition-transform hover:-translate-y-0.5 hover:shadow-xl">
|
||
<video className="w-full aspect-video object-cover block" src="/images/templates/kinetic-type.mp4" poster="/images/templates/kinetic-type.png" muted loop playsInline preload="metadata" />
|
||
<div className="absolute bottom-0 left-0 right-0 pt-6 pb-2 px-3" style={{background: "linear-gradient(transparent, rgba(0,0,0,0.75))"}}><strong className="text-sm font-semibold text-white block">Kinetic Type</strong><span className="text-xs text-zinc-300">Promos & title cards</span></div>
|
||
</div>
|
||
<div className="tpl-card relative rounded-xl overflow-hidden bg-zinc-900 transition-transform hover:-translate-y-0.5 hover:shadow-xl">
|
||
<video className="w-full aspect-video object-cover block" src="/images/templates/decision-tree.mp4" poster="/images/templates/decision-tree.png" muted loop playsInline preload="metadata" />
|
||
<div className="absolute bottom-0 left-0 right-0 pt-6 pb-2 px-3" style={{background: "linear-gradient(transparent, rgba(0,0,0,0.75))"}}><strong className="text-sm font-semibold text-white block">Decision Tree</strong><span className="text-xs text-zinc-300">Explainers & tutorials</span></div>
|
||
</div>
|
||
<div className="tpl-card relative rounded-xl overflow-hidden bg-zinc-900 transition-transform hover:-translate-y-0.5 hover:shadow-xl">
|
||
<video className="w-full aspect-video object-cover block" src="/images/templates/product-promo.mp4" poster="/images/templates/product-promo.png" muted loop playsInline preload="metadata" />
|
||
<div className="absolute bottom-0 left-0 right-0 pt-6 pb-2 px-3" style={{background: "linear-gradient(transparent, rgba(0,0,0,0.75))"}}><strong className="text-sm font-semibold text-white block">Product Promo</strong><span className="text-xs text-zinc-300">Product showcases</span></div>
|
||
</div>
|
||
<div className="tpl-card relative rounded-xl overflow-hidden bg-zinc-900 transition-transform hover:-translate-y-0.5 hover:shadow-xl">
|
||
<video className="w-full aspect-video object-cover block" src="/images/templates/nyt-graph.mp4" poster="/images/templates/nyt-graph.png" muted loop playsInline preload="metadata" />
|
||
<div className="absolute bottom-0 left-0 right-0 pt-6 pb-2 px-3" style={{background: "linear-gradient(transparent, rgba(0,0,0,0.75))"}}><strong className="text-sm font-semibold text-white block">NYT Graph</strong><span className="text-xs text-zinc-300">Data stories</span></div>
|
||
</div>
|
||
</div>
|
||
|
||
## Portrait Templates
|
||
|
||
<div className="not-prose grid grid-cols-3 gap-3 my-6">
|
||
<div className="tpl-card relative rounded-xl overflow-hidden bg-zinc-900 transition-transform hover:-translate-y-0.5 hover:shadow-xl">
|
||
<video className="w-full object-cover block" style={{aspectRatio: "9/16"}} src="/images/templates/vignelli.mp4" poster="/images/templates/vignelli.png" muted loop playsInline preload="metadata" />
|
||
<div className="absolute bottom-0 left-0 right-0 pt-6 pb-2 px-3" style={{background: "linear-gradient(transparent, rgba(0,0,0,0.75))"}}><strong className="text-sm font-semibold text-white block">Vignelli</strong><span className="text-xs text-zinc-300">Headlines & announcements</span></div>
|
||
</div>
|
||
</div>
|
||
|
||
<Tip>
|
||
Looking for a minimal starting point? Use **blank** — it gives you an empty composition with just the scaffolding, no visual design.
|
||
|
||
```bash Terminal
|
||
npx hyperframes init my-video --example blank
|
||
```
|
||
</Tip>
|
||
|
||
## Choosing an Example
|
||
|
||
| Example | Style | Format | Best for |
|
||
|----------|-------|--------|----------|
|
||
| `warm-grain` | Organic, textured | Landscape | Lifestyle, branding, editorial |
|
||
| `play-mode` | Energetic, elastic | Landscape | Social media, product launches |
|
||
| `swiss-grid` | Clean, structured | Landscape | Corporate, data, technical |
|
||
| `kinetic-type` | Dramatic type | Landscape | Promos, intros, title cards |
|
||
| `decision-tree` | Diagrammatic | Landscape | Explainers, tutorials |
|
||
| `product-promo` | Multi-scene | Landscape | Product showcases, demos |
|
||
| `nyt-graph` | Editorial data | Landscape | Data stories, reports |
|
||
| `vignelli` | Bold, typographic | Portrait | Headlines, announcements |
|
||
| `blank` | Minimal scaffolding | — | Full control, agent-generated |
|
||
|
||
## Example Details
|
||
|
||
<Tabs>
|
||
<Tab title="warm-grain">
|
||
### warm-grain
|
||
|
||
Cream-toned aesthetic with grain texture overlay.
|
||
|
||
**What it produces:** A composition with warm color grading, textured grain, and smooth transitions. Includes an intro sub-composition and captions support.
|
||
|
||
```
|
||
my-video/
|
||
├── meta.json
|
||
├── index.html
|
||
├── compositions/
|
||
│ ├── intro.html
|
||
│ ├── graphics.html
|
||
│ └── captions.html
|
||
└── assets/
|
||
```
|
||
</Tab>
|
||
<Tab title="play-mode">
|
||
### play-mode
|
||
|
||
Playful elastic animations with bold, energetic motion.
|
||
|
||
```
|
||
my-video/
|
||
├── meta.json
|
||
├── index.html
|
||
├── compositions/
|
||
│ ├── intro.html
|
||
│ ├── stats.html
|
||
│ └── captions.html
|
||
└── assets/
|
||
```
|
||
</Tab>
|
||
<Tab title="swiss-grid">
|
||
### swiss-grid
|
||
|
||
Structured grid layout inspired by Swiss/International Typographic Style.
|
||
|
||
```
|
||
my-video/
|
||
├── meta.json
|
||
├── index.html
|
||
├── compositions/
|
||
│ ├── intro.html
|
||
│ ├── graphics.html
|
||
│ └── captions.html
|
||
└── assets/
|
||
```
|
||
</Tab>
|
||
<Tab title="vignelli">
|
||
### vignelli
|
||
|
||
Bold typography with red accents (1080×1920 portrait).
|
||
|
||
```
|
||
my-video/
|
||
├── meta.json
|
||
├── index.html
|
||
├── compositions/
|
||
│ ├── overlays.html
|
||
│ └── captions.html
|
||
└── assets/
|
||
```
|
||
</Tab>
|
||
<Tab title="kinetic-type">
|
||
### kinetic-type
|
||
|
||
Bold kinetic typography promo with dramatic text animations.
|
||
|
||
```
|
||
my-video/
|
||
├── meta.json
|
||
├── index.html
|
||
└── compositions/
|
||
└── main-graphics.html
|
||
```
|
||
</Tab>
|
||
<Tab title="decision-tree">
|
||
### decision-tree
|
||
|
||
Animated flowchart with branching paths and progressive reveal.
|
||
|
||
```
|
||
my-video/
|
||
├── meta.json
|
||
├── index.html
|
||
└── compositions/
|
||
└── decision_tree.html
|
||
```
|
||
</Tab>
|
||
<Tab title="product-promo">
|
||
### product-promo
|
||
|
||
Multi-scene product showcase with SVG assets.
|
||
|
||
```
|
||
my-video/
|
||
├── meta.json
|
||
├── index.html
|
||
├── compositions/
|
||
│ ├── scene1-logo-intro.html
|
||
│ ├── scene2-4-canvas.html
|
||
│ └── scene5-logo-outro.html
|
||
└── assets/
|
||
├── figma-cursors.svg
|
||
├── figma-logo-pieces.svg
|
||
└── figma-logo-pills.svg
|
||
```
|
||
</Tab>
|
||
<Tab title="nyt-graph">
|
||
### nyt-graph
|
||
|
||
Animated data chart in print editorial style.
|
||
|
||
```
|
||
my-video/
|
||
├── meta.json
|
||
├── index.html
|
||
└── compositions/
|
||
└── nyt-chart.html
|
||
```
|
||
</Tab>
|
||
<Tab title="blank">
|
||
### blank
|
||
|
||
Empty composition with just the scaffolding.
|
||
|
||
```
|
||
my-video/
|
||
├── meta.json
|
||
├── index.html
|
||
└── compositions/
|
||
└── captions.html
|
||
```
|
||
</Tab>
|
||
</Tabs>
|
||
|
||
## Passing a Source Video
|
||
|
||
```bash Terminal
|
||
npx hyperframes init my-video --example warm-grain --video ./my-clip.mp4
|
||
```
|
||
|
||
The CLI will probe the video for duration, resolution, and codec. If the video uses an incompatible codec, it will be automatically transcoded to H.264 MP4 if FFmpeg is available.
|
||
|
||
## Custom Examples
|
||
|
||
Any directory with an `index.html` can serve as an example. Your custom example needs:
|
||
|
||
1. An `index.html` with a [`data-composition-id`](/concepts/data-attributes#composition-attributes) root element
|
||
2. A [GSAP timeline](/guides/gsap-animation) registered in `window.__timelines`
|
||
3. Any assets in the same directory or a subdirectory
|
||
|
||
```html index.html
|
||
<div id="root" data-composition-id="my-example"
|
||
data-start="0" data-width="1920" data-height="1080">
|
||
|
||
<!-- Your elements here -->
|
||
|
||
<script src="https://cdn.jsdelivr.net/npm/gsap@3/dist/gsap.min.js"></script>
|
||
<script>
|
||
const tl = gsap.timeline({ paused: true });
|
||
// Add your animations...
|
||
window.__timelines = window.__timelines || {};
|
||
window.__timelines["my-example"] = tl;
|
||
</script>
|
||
</div>
|
||
```
|
||
|
||
After creating a custom example, validate it with the [linter](/packages/cli#lint):
|
||
|
||
```bash Terminal
|
||
npx hyperframes lint
|
||
```
|
||
|
||
## Next Steps
|
||
|
||
<CardGroup cols={2}>
|
||
<Card title="Quickstart" icon="rocket" href="/quickstart">
|
||
Create, preview, and render your first video
|
||
</Card>
|
||
<Card title="GSAP Animation" icon="wand-magic-sparkles" href="/guides/gsap-animation">
|
||
Add animations to your example
|
||
</Card>
|
||
<Card title="Compositions" icon="layer-group" href="/concepts/compositions">
|
||
Understand the composition data model
|
||
</Card>
|
||
<Card title="Rendering" icon="film" href="/guides/rendering">
|
||
Render your composition to MP4
|
||
</Card>
|
||
</CardGroup>
|