mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-03 12:54:29 +00:00
v0.6.17
24
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
73cb5a5b55 |
fix(studio,registry): unbreak studio test on main + make vignette demo legible
Two surgical changes, both isolated to the catalog-previews flow: 1. `packages/studio/src/player/hooks/usePlaybackKeyboard.test.ts` PR #842 changed `seek()` to take `(time, { keepPlaying: true })` for the A/E shortcuts. The keyboard-layout tests added by #839 still asserted the single-arg form. Both landed on main without cross-checking, so `main` itself has been failing Test/Windows since. Update the two assertions to match the new signature. Same fix Miguel already authored on `feat/studio-preview-pasteboard-bg`. 2. `registry/components/vignette/demo.html` The original demo captured a frame where the vignette was at its weakest point — the effect was nearly invisible in the static preview used by docs. Reworked the demo so: - The backdrop is a layered "cinematic still" (warm key + teal rim + dark falloff) and includes a centered subject ("moon"), so the vignette has a focal point to frame. - Vignette starts soft (size 70%, alpha 0.35) and ramps to a dramatic cinematic vignette (size 26%, alpha 0.92) over 1.6s. - Peak intensity holds across t≈3.0s, which is exactly where the catalog script samples the thumbnail (`Math.min(3.0, duration*0.6)` with duration=5). - Breathing motion in t=3.4–5.2s gives the video loop visible life without disturbing the still frame. |
||
|
|
0c74f4ed89 |
feat(registry): add vignette CSS component
Pure-CSS radial darkening overlay that fills its positioned parent and pulls focus toward the center. Shape, size, and color are exposed as CSS custom properties (--vignette-shape, --vignette-size, --vignette-edge, --vignette-color), so a GSAP timeline can animate any of them — the snippet's header comment shows the pattern for fading the vignette in. The Components section currently has four entries; this fills the cinematic-cinematography gap a video editor expects out of the box without bundling any asset (the effect is a single radial-gradient). Default z-index 90 sits below grain-overlay (100) so grain reads on top of the darkened corners. Catalog page, registry index, and nav are regenerated via scripts/generate-catalog-pages.ts. |
||
|
|
edac92b431 |
docs: add texture mask text catalog entry (#650)
* feat(registry): add texture mask PNGs for texture-mask-text component * feat(registry): add texture-mask-text CSS snippet * feat(registry): add registry-item.json for texture-mask-text * feat(registry): add texture-mask-text demo composition * feat(registry): register texture-mask-text component in manifest * style: format texture-mask-text files with oxfmt * fix: set mask-image directly on texture classes instead of via CSS custom property url() inside CSS custom properties doesn't resolve correctly with mask-image in some browsers. Move mask-image declarations to each texture class directly. * docs: add texture mask text catalog entry * test: lint texture mask text usage * fix: harden texture mask text docs and lint * fix: stabilize texture mask asset paths * fix: address texture catalog review feedback * fix: harden texture mask text instructions * docs: remove texture catalog intro copy * docs: use canonical texture preview URL * docs: use cdn texture mask assets * fix: escape catalog frontmatter safely * test: stabilize windows render cli test * test: pin texture catalog instructions |
||
|
|
632731b076 |
fix(player): replay from start when play is pressed after video ends (#649)
* fix(player): replay from start when play is pressed after video ends When a non-looping composition reaches its end, pressing play again had no effect because the playhead stayed at the final frame. Now play() detects the ended state and seeks to 0 before resuming. * chore: fix pre-existing format issues in registry files |
||
|
|
869a3763b2 |
feat(catalog): HyperFrames branding, HTML-in-Canvas guide, remove captions (#647)
* docs: group VFX blocks under HTML-in-Canvas, captions under Captions in sidebar * docs: add HTML-in-Canvas guide, Chrome flag disclaimer, remove captions - Add docs/guides/html-in-canvas.mdx — comprehensive guide covering the API, feature detection, re-capture patterns, and catalog blocks - Add Chrome flag Warning banner to every HTML-in-Canvas block page - Remove captions blocks from registry (will ship separately) - Add html-in-canvas guide to docs navigation (top of Guides section) * feat: update liquid glass, portal, shatter with HyperFrames branding Replace generic placeholder content with HyperFrames-themed text: - Liquid Glass: 'Ship videos 10x faster' with stats and gradient text - Portal: 'Write HTML / Render Video' with HyperFrames nav - Shatter: 'HTML is Video' with render speed/file size metrics Re-rendered and uploaded preview videos to S3. |
||
|
|
0f3b207b23 | fix: format JSON files, remove unused function, fix capture test mocks | ||
|
|
b7f4c6d0d3 | chore: remove competitor mentions from block source files | ||
|
|
73c4aaf08d | style: format all block HTML files with oxfmt | ||
|
|
20c1341cc8 |
feat(cli): name-or-tag resolution for hyperframes add
hyperframes add now auto-detects whether the argument is a single block name or a tag. No --tag flag needed: hyperframes add html-in-canvas # installs all 7 html-in-canvas blocks hyperframes add captions # installs all 5 caption blocks hyperframes add vfx-shatter # installs one block When the name doesn't match a registry item, the CLI falls back to tag-based resolution and bulk-installs all matching blocks. Also fixes tag assignments: - VFX blocks tagged "html-in-canvas" (not "vfx") - Caption blocks tagged "captions" only (no html-in-canvas) |
||
|
|
3ad51235c8 |
feat(registry): add html-in-canvas tag to all VFX and caption blocks
All 12 blocks now share the 'html-in-canvas' tag, enabling: hyperframes add --tag html-in-canvas This installs all VFX + caption blocks in one command. |
||
|
|
da95f6c7ad | fix: correct composition IDs and add data-root to vfx-liquid-background | ||
|
|
a68191efe1 |
feat(registry): add VFX and Captions block categories
Add 12 new registry blocks across two new categories: **VFX Blocks (7):** - vfx-text-cursor: dramatic text reveal with cursor glow and chromatic shadows - vfx-liquid-background: organic liquid simulation with vertex displacement - vfx-iphone-device: real GLTF iPhone + MacBook with live HTML screens - vfx-magnetic: magnetic field particle visualization - vfx-portal: dimension breach portal transition - vfx-liquid-glass: Voronoi glass fracture with parallax reveal - vfx-shatter: glass shatter with physics-driven fragments **Caption Blocks (5):** - captions-slam: bold uppercase scale-pop with back.out overshoot - captions-karaoke: word-by-word color reveal on frosted glass pill - captions-minimal: clean Netflix-subtitle style fade - captions-bounce: playful elastic bounce with colorful word pills - captions-cinematic: elegant slow fade with letter-spacing animation All blocks include registry-item.json and are registered in registry.json. VFX blocks use experimental stability, caption blocks use stable. |
||
|
|
cd277ca312 |
feat(catalog): add Blue Sweater intro showcase (#630)
## Problem The Blue Sweater intro HyperFrames project was only available as a standalone exported project zip. It was not installable from the public registry or visible in the Catalog Showcases group. ## What this fixes Adds `blue-sweater-intro-video` as a registry block with its composition, avatar image, and sound mix asset. The block is exposed through the generated catalog page, `docs/public/catalog-index.json`, and the Showcases navigation. The manifest and generated catalog page credit the creator as [Joe Sai](https://x.com/_blue_sweater_). ## Root cause Catalog-visible blocks are driven by `registry/registry.json`, each block's `registry-item.json`, generated docs/catalog files, and CDN-hosted preview media. The exported project had a valid standalone composition, but it had not been converted into that registry/catalog contract or uploaded to the docs preview CDN. ## Verification ### Local checks - `bun install` - `bun run build` - `bunx tsx scripts/generate-catalog-pages.ts` - `bun run generate:catalog-previews -- --only blue-sweater-intro-video` - `bun packages/cli/src/cli.ts add blue-sweater-intro-video --dir /tmp/hf-blue-sweater-install-test --no-clipboard --json` against a locally served registry - `bun packages/cli/src/cli.ts lint /tmp/hf-blue-sweater-install-test` returned 0 errors and 3 static GSAP overlap warnings from the supplied timeline/parser path - `bun packages/cli/src/cli.ts validate /tmp/hf-blue-sweater-install-test --timeout 5000` returned 0 runtime errors and 0 warnings, with contrast audit warnings only - `bun packages/cli/src/cli.ts inspect /tmp/hf-blue-sweater-install-test --at 0.5,2.5,5.5,9.8,11.2 --json` returned 0 layout issues - `bun packages/cli/src/cli.ts render /tmp/hf-blue-sweater-install-test --output /tmp/hf-blue-sweater-install-test/blue-sweater-intro-video-render.mp4 --fps 24 --quality draft --workers 3` - `ffprobe` reported the installed render duration as `12.000000` - `bunx oxfmt --check registry/registry.json registry/blocks/blue-sweater-intro-video/registry-item.json registry/blocks/blue-sweater-intro-video/blue-sweater-intro-video.html docs/docs.json docs/public/catalog-index.json docs/catalog/blocks/blue-sweater-intro-video.mdx` - `git diff --check` - `bunx vitest run packages/cli/src/commands/add.test.ts packages/core/src/registry/types.test.ts` ### Browser verification - Started a real local HyperFrames preview for the installed test project. - Used `agent-browser` to open `http://localhost:5198/api/projects/hf-blue-sweater-install-test/preview` at 1920x1080. - Verified the runtime registered `install-test` and `blue-sweater-intro-video` timelines. - Sought the block to the final card and verified `@_blue_sweater_` and the following state were visible. - Recorded an `agent-browser`-driven full animation pass; `ffprobe` confirmed a 1920x1080 WebM with 110 video frames. - Checked the fresh `agent-browser` session for page errors after the direct preview flow: `errors: []`. - Used `agent-browser` to load an HTML page with the exact generated CDN `video`/`poster` URLs; the browser reported `readyState: 4`, `videoWidth: 1920`, `videoHeight: 1080`, and `paused: false`. ### CDN upload Uploaded the generated preview media with AWS CLI to the existing docs image bucket path: - `s3://heygen-public/hyperframes-oss/docs/images/catalog/blocks/blue-sweater-intro-video.mp4` - `s3://heygen-public/hyperframes-oss/docs/images/catalog/blocks/blue-sweater-intro-video.png` Verified both public CDN URLs return `HTTP 200` with correct content type and immutable cache headers: - `https://static.heygen.ai/hyperframes-oss/docs/images/catalog/blocks/blue-sweater-intro-video.mp4` (`video/mp4`) - `https://static.heygen.ai/hyperframes-oss/docs/images/catalog/blocks/blue-sweater-intro-video.png` (`image/png`) ## Notes - Local-only browser proof artifacts: - `/tmp/hf-blue-sweater-browser-proof/fresh-final-card.png` - `/tmp/hf-blue-sweater-browser-proof/fresh-browser-flow.webm` - `/tmp/hf-blue-sweater-cdn-check.png` - Local-only installed render artifact: - `/tmp/hf-blue-sweater-install-test/blue-sweater-intro-video-render.mp4` |
||
|
|
7affa4a4e9 |
fix: handle player loop and render exit (#617)
## Problem Two newly reported runtime issues break common local workflows: - Fixes #615: `<hyperframes-player loop>` reaches the final frame, receives a paused runtime state, and stays paused instead of wrapping. - Fixes #616: `hyperframes render` can finish writing the output and print `Render complete`, but still remain alive when a non-essential handle keeps Node's event loop open. The catalog block also used old VPN branding and slug/file names that should now be neutral. Renaming registry items also exposed a catalog-preview CI bug where deleted registry paths were treated as still-renderable changed items. ## What this fixes - detects player completion from the previous playing state before mutating the parent `_paused` cache from the runtime's final state - wraps looping players back to `0` and immediately resumes playback even when the runtime posts `isPlaying: false` at the end frame - keeps non-looping players dispatching the existing `ended` flow - lets the CLI command path schedule a short unref'd `process.exit(0)` after a successful local or Docker render - keeps `renderLocal()` importable for tests and internal callers without forcing process exit unless the CLI command explicitly opts in - adds regression coverage for the player loop end-state and successful render exit scheduling - renames the VPN catalog block to `vpn-youtube-spot` across registry, docs route, install command, composition filename, asset filename, composition id, and timeline key - keeps visible block/app copy friendly and named `VPN` - updates catalog-preview CI to ignore deleted registry paths when computing changed preview items ## Root cause The player message handler updated `_paused = !data.isPlaying` before checking for end-of-composition loop behavior. The runtime's legitimate final-frame state has `isPlaying: false`, so the existing `currentTime >= duration && !paused` loop branch was skipped. For render completion, the CLI returned after `printRenderComplete()`, leaving process lifetime entirely to Node's active handles. Most local renders in this checkout drain cleanly, but the reported npm flow shows a sleeping parent process after output is already complete. The CLI now schedules a short unref'd successful exit only from the command path after user-visible render work has completed. The catalog block issue was content/metadata drift: registry/docs/code identifiers still used the old slug, so the catalog route, install command, composition id, file names, and source prompt did not match the requested neutral VPN naming. The preview workflow used plain `git diff --name-only`, which includes deleted paths during renames; it now filters to added/copied/modified/renamed live paths. ## Verification ### Local checks - `bun run build:hyperframes-runtime` - `bun run --filter @hyperframes/player test -- src/hyperframes-player.test.ts` - `bun run --filter @hyperframes/cli test -- src/commands/render.test.ts` - `bun run --filter @hyperframes/player typecheck` - `bun run --filter @hyperframes/cli typecheck` - `bunx oxfmt --check packages/player/src/hyperframes-player.ts packages/player/src/hyperframes-player.test.ts packages/cli/src/commands/render.ts packages/cli/src/commands/render.test.ts` - `bunx oxlint packages/player/src/hyperframes-player.ts packages/player/src/hyperframes-player.test.ts packages/cli/src/commands/render.ts packages/cli/src/commands/render.test.ts` - `bun run --filter @hyperframes/player build` - `bun run --filter @hyperframes/studio build` - `bun run --filter @hyperframes/cli build` - `bunx oxfmt --check registry/blocks/vpn-youtube-spot/vpn-youtube-spot.html registry/blocks/vpn-youtube-spot/registry-item.json registry/registry.json docs/catalog/blocks/vpn-youtube-spot.mdx docs/docs.json docs/public/catalog-index.json` - `bunx oxlint registry/blocks/vpn-youtube-spot/vpn-youtube-spot.html registry/blocks/vpn-youtube-spot/registry-item.json registry/registry.json docs/catalog/blocks/vpn-youtube-spot.mdx docs/docs.json docs/public/catalog-index.json` - `bunx oxfmt --check .github/workflows/catalog-previews.yml` - `BASE_SHA=26b8e2a9853eb1a8f77c05fb0c8f0903cdb2cf18; git diff --name-only --diff-filter=ACMR "$BASE_SHA"...HEAD -- registry/blocks/ registry/components/ ...` returns only `vpn-youtube-spot` - `npx tsx scripts/sync-schemas.ts --check` - `npx mint validate` from `docs/` - `npx mint broken-links` from `docs/` - `git diff --check` - Lefthook pre-commit: format pass - Lefthook commit-msg: commitlint pass ### Browser verification - Built the player bundle and served a real local reproduction using the built player, the built HyperFrames runtime, and GSAP. - Used `agent-browser` to open the page, click `Seek near end`, and wait through the end-frame transition. - Verified the browser state after playback: `stuck=false`, `looped=true`, and playback continued after wrapping from ~4s back to the start. - Served `registry/blocks/vpn-youtube-spot/vpn-youtube-spot.html` locally, used `agent-browser` to seek the timeline, and verified `window.__timelines` contains `vpn-youtube-spot`, not `goonvpn-youtube-spot`. - Served the docs locally with Mintlify, opened `/catalog/blocks/vpn-youtube-spot`, and verified the install command is `npx hyperframes add vpn-youtube-spot` with no old slug visible. ### Composition verification - `bun run --filter @hyperframes/cli dev lint /var/folders/3n/hxk3qmnd0tl284jtcy66w6dw0000gn/T/hf-vpn-renamed-w027if` returned 0 errors and 1 existing large-composition warning. - `bun run --filter @hyperframes/cli dev validate /var/folders/3n/hxk3qmnd0tl284jtcy66w6dw0000gn/T/hf-vpn-renamed-w027if --timeout 5000` returned 0 console errors; it reported existing non-fatal contrast audit warnings from the block styling. - `bun run --filter @hyperframes/cli dev render /var/folders/3n/hxk3qmnd0tl284jtcy66w6dw0000gn/T/hf-vpn-renamed-w027if --output /tmp/hf-vpn-renamed-proof.mp4 --fps 30 --quality draft --workers 1 --no-browser-gpu` completed successfully. - `ffprobe -v error -show_entries format=duration,size -of default=noprint_wrappers=1 /tmp/hf-vpn-renamed-proof.mp4` reported `duration=7.000000`. ### Render verification - Ran a real 1920x1080, 5-second render with `--gpu --workers 6 --quality draft --fps 24`. - Verified the command printed `Render complete` and the parent process exited with code `0` in the wrapper: `RENDER_EXIT_PROOF code=0 signal=null sawComplete=true`. ## Notes - I could not reproduce the exact indefinite #616 render hang on this checkout; both tiny and GPU/6-worker local renders exited cleanly before and after the patch. The CLI guard still addresses the reported leaked-handle failure mode because it fires only after successful render completion. - Browser proof artifacts were local-only: `/tmp/hf-player-loop-proof-final.png`, `/tmp/hf-player-loop-proof-final.webm`, `/tmp/hf-vpn-code-rename-proof.png`, `/tmp/hf-vpn-code-rename-proof.webm`, `/tmp/hf-vpn-doc-route-rename-proof.png`, and `/tmp/hf-vpn-doc-route-rename-proof.webm`. - The renamed composition render artifact was local-only: `/tmp/hf-vpn-renamed-proof.mp4`. - The CLI exit guard is only enabled by the `render` command's top-level local/Docker calls. Direct test/internal calls to `renderLocal()` do not force process exit unless they pass `exitAfterComplete: true`. |
||
|
|
4d05b475f0 |
feat: add Stronkter catalog blocks (#570)
## Problem The Catalog did not include the four prompt-matched Stronkter one-shot HyperFrames projects, and registry metadata only supported a plain author string, so there was no structured way to show creator attribution or the original generation prompt on generated catalog pages. ## What this fixes - Adds four Catalog blocks matching the provided prompts, in order: - `north-korea-locked-down` - `apple-money-count` - `nyc-paris-flight` - `goonvpn-youtube-spot` - Attributes each block to [Stronkter](https://x.com/Stronkter). - Stores and renders the original source prompt for each generated catalog page. - Adds a local realistic map plate for the North Korea block so rendering does not depend on live map tile requests. - Extends registry item metadata/schema with `authorUrl` and `sourcePrompt`. - Updates catalog page generation to read items from `registry/registry.json`, keeping generated docs aligned to the public registry manifest. - Ignores normal browser media preload `net::ERR_ABORTED` request failures for media assets during `hyperframes validate`, while preserving failures for real missing assets. ## Root cause The imported projects are Catalog-ready compositions, but the registry/docs pipeline did not have first-class source-prompt or linked-author fields to expose creator credit on generated MDX pages. The audio-backed compositions also surfaced a validation edge case: Chrome can report aborted media preload requests as `net::ERR_ABORTED` even when the audio file exists and playback is valid. ## Verification ### Local - `bun run --filter @hyperframes/cli test src/commands/validate.test.ts` - `bun run --filter @hyperframes/core test src/registry/types.test.ts` - `bun run sync-schemas:check` - `bunx oxlint packages/cli/src/commands/validate.ts packages/cli/src/commands/validate.test.ts packages/core/src/registry/types.ts packages/core/src/registry/types.test.ts scripts/generate-catalog-pages.ts` - `bunx oxfmt --check ...` on changed source, registry, docs, and composition files - `git diff --check` - `bun packages/cli/src/cli.ts lint` and `validate` against temp installed projects for all four blocks - Lefthook pre-commit: lint/format/typecheck on the initial commit, plus format on the amend - Lefthook commit-msg: commitlint ### Browser - Exercised all four blocks through HyperFrames preview routes with `agent-browser`. - Captured playback screenshots and WebM recordings for: - `north-korea-locked-down` - `apple-money-count` - `nyc-paris-flight` - `goonvpn-youtube-spot` ## Notes - The zip also contained unrelated project directories, but this PR intentionally includes only the four prompt-matched Catalog blocks requested here. - The imported one-shot compositions may trigger the existing large-composition lint warning, but there are no lint errors and runtime validation passes. |
||
|
|
328bba0384 | fix: make registry blocks pass lint errors (#564) | ||
|
|
c0a74c1159 | feat: add vertical flowchart block (#563) | ||
|
|
9943091247 |
feat(registry): seed transition blocks — 14 shader + 14 CSS showcase (#270)
## What Add 28 transition blocks from the Hyperframe Template Structure catalog, bringing the registry to 53 total items. ### Shader transitions (14 blocks, WebGL, 4s each) `domain-warp-dissolve`, `ridged-burn`, `whip-pan`, `sdf-iris`, `ripple-waves`, `gravitational-lens`, `cinematic-zoom`, `chromatic-radial-split`, `glitch`, `swirl-vortex`, `thermal-distortion`, `flash-through-white`, `cross-warp-morph`, `light-leak` ### CSS transition showcases (14 blocks, various durations) `transitions-3d`, `transitions-blur`, `transitions-cover`, `transitions-destruction`, `transitions-dissolve`, `transitions-distortion`, `transitions-grid`, `transitions-light`, `transitions-mechanical`, `transitions-other`, `transitions-push`, `transitions-radial`, `transitions-scale`, `transitions-shader` ## Why Phase D content accumulation. Transitions are the most-requested category for the catalog. ## How - Shader transitions extracted from `shader-showcase.zip`, each a standalone HTML with WebGL shaders - CSS transitions extracted from `showcase-bundle.zip`, each a standalone showcase page - All tagged with `transition` + `shader` or `showcase` for catalog grouping - Preview thumbnails generated for all 28 blocks - Catalog pages + index regenerated ## Test plan - [x] All 28 blocks produce preview thumbnails - [x] `registry-item.json` validates for all blocks - [x] Catalog pages generated (45 total items in catalog-index.json) - [x] `oxfmt --check` passes |
||
|
|
d37d738be9 |
feat(registry): seed blocks batch — social overlays, data viz, showcases (#269)
## What Add 11 blocks from the Hyperframe Template Structure catalog, bringing the registry to 25 total items. ### Social overlays | Block | Dimensions | Duration | Description | |-------|-----------|----------|-------------| | `instagram-follow` | 1080×1920 | 4.5s | Instagram follow overlay with profile card | | `tiktok-follow` | 1080×1920 | 4.5s | TikTok follow overlay with profile card | | `yt-lower-third` | 1920×1080 | 4.5s | YouTube subscribe lower third | | `x-post` | 1920×1080 | 5s | X/Twitter post card with engagement | | `reddit-post` | 1920×1080 | 5s | Reddit post card with upvotes | | `spotify-card` | 1080×1920 | 5s | Spotify now-playing card | | `macos-notification` | 1920×1080 | 5s | macOS notification banner | ### Data & visualization | Block | Duration | Description | |-------|----------|-------------| | `ascii-dashboard` | 10s | Retro terminal-style data viz | | `ascii-lightning` | 9s | ASCII art lightning bolt animation | ### Showcases | Block | Duration | Description | |-------|----------|-------------| | `app-showcase` | 5.5s | Floating smartphone screens | | `ui-3d-reveal` | 13s | Perspective 3D UI reveal | ## Why Phase D content accumulation. The registry pipeline (PRs 6-10) is in place — this PR exercises it at scale. ## How - Extracted from zip files in the Hyperframe Template Structure Notion doc - Social overlays: single-file standalone HTML, copied directly - Multi-file blocks (ascii-*, app-showcase, ui-3d-reveal): converted `<template>` sub-compositions to standalone HTML with proper `<!doctype>` wrappers - All previews (PNG + MP4) rendered locally via `generate-catalog-previews.ts` - Catalog MDX pages regenerated via `generate-catalog-pages.ts` - `docs.json` updated with new catalog entries ## Test plan - [x] All 11 blocks render to PNG + MP4 without errors - [x] Catalog pages generated for all 17 items (14 blocks + 3 components) - [x] `registry-item.json` files have correct dimensions, duration, tags - [x] `oxfmt --check` passes on all files |
||
|
|
4bde66f532 |
feat(skills): hyperframes-registry skill (#261)
## What
New skill `hyperframes-registry` that teaches AI coding agents how to install and wire registry blocks and components into HyperFrames compositions.
### Skill structure
```
skills/hyperframes-registry/
SKILL.md — triggers, overview, quick reference
references/
install-locations.md — default paths, hyperframes.json config
wiring-blocks.md — iframe inclusion, data attributes, positioning
wiring-components.md — snippet merging (HTML, CSS, JS, timeline)
discovery.md — manifest reading, item fields, available items table
demo-html-pattern.md — why components ship demo.html, structure conventions
examples/
add-block.md — worked example: data-chart block install + wiring
add-component.md — worked example: shimmer-sweep component install + wiring
```
## Why
Phase B of the catalog plan (PR 10). Without this skill, agents using `hyperframes add` have to guess how to wire installed items into compositions. The skill encodes the iframe/snippet patterns so agents get it right on the first attempt.
## How
- SKILL.md frontmatter triggers on: `hyperframes add`, "block", "component", `hyperframes.json`
- References cover every step: discovery, install, wiring blocks (iframe), wiring components (snippet merge), and the demo.html convention
- Two worked examples walk through complete install-to-preview workflows
- Updated CLAUDE.md skills table + trigger rules, README.md skills table, docs/packages/cli.mdx
## Test plan
- [x] `scripts/lint-skills.ts` passes (checked 4 skill files, no issues)
- [x] `oxfmt --check` passes on all markdown files
- [x] SKILL.md frontmatter has valid `name` and `description`
- [x] All reference links in SKILL.md resolve to existing files
- [x] CLAUDE.md, README.md, and docs CLI page updated with new skill
|
||
|
|
b0f754a7f7 |
feat(registry): seed components — grain-overlay, shimmer-sweep, grid-pixelate-wipe (#260)
## What Three reusable effect components for the registry, each with a snippet HTML and companion `demo.html`: | Component | Description | |-----------|-------------| | `grain-overlay` | Animated film grain texture overlay (CSS keyframes, extracted from warm-grain example) | | `shimmer-sweep` | CSS gradient light sweep across text/elements, driven by GSAP custom property animation | | `grid-pixelate-wipe` | Grid-based dissolve transition — screen breaks into 16×9 squares that scale in/out with stagger | Establishes the `demo.html` convention in `CONTRIBUTING.md`. ## Why Phase B of the catalog plan — seed the first components in the registry. Components are effect snippets that get merged into existing compositions (vs. blocks which are standalone sub-compositions). ## How - **grain-overlay**: Extracted the grain texture pattern from the warm-grain example. Uses a 200% oversized tiled texture with `steps(1)` keyframe animation for the random-noise effect. - **shimmer-sweep**: Original implementation using CSS custom properties (`--shimmer-pos`) animated by GSAP. The gradient mask uses `mix-blend-mode: overlay` for a natural light sweep. Auto-injects `.shimmer-mask` elements into `.shimmer-sweep-target` wrappers. - **grid-pixelate-wipe**: Creates a 16×9 CSS Grid of cells, animated with GSAP stagger. Users drive `.grid-cell` `scale` directly in their timeline. Simplify review addressed: scoped `.grain-texture` under `#grain-overlay`, scoped `.grid-cell` under `#grid-pixelate-overlay`, removed `window.gridPixelateIn/Out` globals in favor of direct GSAP patterns. Each component ships a `demo.html` — a standalone composition that previews the effect and doubles as a fixture for the CI preview pipeline (PR 8). ## Test plan - [x] `hyperframes add grain-overlay` installs to `compositions/components/grain-overlay.html` - [x] `hyperframes add shimmer-sweep` installs to `compositions/components/shimmer-sweep.html` - [x] `hyperframes add grid-pixelate-wipe` installs to `compositions/components/grid-pixelate-wipe.html` - [x] All three return correct `--json` output with snippet and type info - [x] `registry-item.json` files validate against the JSON Schema - [x] `demo.html` files are self-contained with correct `data-composition-id` and `window.__timelines` registration - [x] `oxfmt --check` and `oxlint` pass on all files - [x] `CONTRIBUTING.md` documents the `demo.html` convention and registry item checklist |
||
|
|
4685e5cd74 |
feat(registry): seed blocks — data-chart, flowchart, logo-outro (#259)
Extract three standalone blocks from existing example templates: - data-chart: Animated bar + line chart with staggered reveal (from nyt-graph) - flowchart: Decision tree with SVG connectors and cursor interaction (from decision-tree) - logo-outro: Cinematic logo reveal with tagline and URL pill (from product-promo) Each block is a complete HTML composition installable via `hyperframes add <name>`. Blocks render as iframes in host compositions. |
||
|
|
969474e843 |
feat(cli): registry resolver + installer (#254)
## What PR 3/17 of the catalog system rollout. Introduces the registry resolver/installer abstraction. No UX change — `init --template` still works identically. Stacks on #253. **New module: `packages/cli/src/registry/`** - `remote.ts` — fetches manifests (`registry.json`, `registry-item.json`) and item files from a GitHub-hosted registry. 24h cache on manifests; item files stream straight to `destDir` - `resolver.ts` — `listRegistryItems`, `loadAllItems` (parallel fetch for picker UX), `resolveItem` (single-item fetch with `Available:` error) - `installer.ts` — `assertSafeTarget` (runtime path-traversal guard) + `installItem` (parallel file download with up-front validation; all-or-nothing semantics) - `index.ts` — barrel **Registry content:** - `registry/registry.json` — top-level manifest in PR 1's `RegistryManifest` shape. 8 examples - `registry/examples/<id>/registry-item.json` — per-item manifest for each existing example, generated from legacy `templates.json` + HTML data-attribute probing - `registry/examples/templates.json` — **deleted**, replaced by the above **Compat layer:** - `packages/cli/src/templates/{remote,generators}.ts` — thin shims that delegate to `../registry/`, keeping `init.ts`'s existing imports stable. `init.ts` doesn't move to the new API until PR 5 where it's part of a larger UX pass **Tooling:** - `scripts/generate-registry-items.ts` — idempotent one-off generator for this PR, kept in-repo for future example additions (`--only <name>` flag) Design doc: [Hyperframes Catalog System](https://www.notion.so/heygen/Hyperframes-Catalog-System-Design-Plan-341449792c69813f899dcd53b4c0383a). Tracker entry in local `hyperframes-catalog-plan.md`. ## Why Every future PR (`hyperframes add`, seed blocks, seed components, custom registries) otherwise has to keep piling onto the ad-hoc fetch + `cpSync` pattern in the old `fetchRemoteTemplate`. The new module is the single place that understands the registry wire format and file layout. **This is also where PR 1's schema comes alive.** ## How ### Scope-trimmed from the plan - **No transitive dependency resolution yet.** Examples have no deps today. `resolveItem` doesn't walk `registryDependencies`; PR 5 adds that when blocks/components need it. - **No ajv schema validation yet.** TS types + runtime path-traversal guard are the only safety nets. Full JSON-Schema validation lands when the registry starts accepting third-party content (PR 14 / custom registries). - **init.ts refactor deferred to PR 5.** Compat shims keep this PR small and reviewable. PR 5 rewrites init alongside adding the `add` command. ### Safety - `assertSafeTarget` rejects absolute paths, `..` segments, Windows drive letters, and any target that `path.resolve` shows to escape `destDir`. Mirrors the PR 1 schema `pattern`/`not.anyOf` on `target`, but runs at install-time so a registry that bypasses schema validation still can't write outside the project - Up-front validation in `installItem` means a malformed item fails **before** any file is written. Atomic-ish semantics: all files land or none do ### Caching - 24h manifest cache lives at `~/.hyperframes/cache/` per existing convention, but now keyed by `<baseUrl>__<kind>__<name>.json` so PR 14 custom registries can coexist ## Test plan - [x] `bun run test` in `packages/cli`: **70 passed** (was 57 on #253, +13). Same 4 pre-existing failures (SRT/VTT whisper normalizer + `lintProject` clean-project test) — identical to main. No regressions - [x] **Resolver unit tests (8):** filter by type, parallel load with fail-safe, resolve-by-name with `Available:` error message, unreachable-registry handling - [x] **Installer unit tests (5):** accepts simple relative paths, rejects `..` segments, rejects Unix absolute paths, rejects Windows drive letters, permits `.` and dotfile-like names - [x] **Smoke test**: `hyperframes init /tmp/x --template blank` (bundled code path, unchanged) works end-to-end - [x] `bunx oxfmt --check` + `bunx oxlint`: clean - [x] Pre-commit typecheck (core + studio): clean. CLI typecheck has 2 pre-existing errors (`render.ts`, `studioServer.ts` — unrelated `"mov"` format issue on main) - [ ] **Smoke test remote fetch (`--template warm-grain`)** — verifiable only post-merge; registry paths live on `main` after this PR lands ## Breaking / migration **No end-user-visible UX change.** `init --template <name>` still works the same way. Internally, `templates.json` is gone and the CLI now reads `registry.json` + `registry-item.json` per example. Installed CLIs on old versions (`hyperframes@0.1.0`–`0.3.0`) already broke at PR 2 merge (see #253 rollout note). The next CLI release after this lands (`0.3.1`+) is the full fix. ## Commits 1. `generate-registry-items.ts` + generated manifests + deleted `templates.json` 2. Resolver + installer + compat shims 3. Unit tests (All squashed into one commit on this branch; see `git log feat/registry-resolver ^refactor/registry-examples-dir`.) ## Stacks on #253 — base branch. When #253 merges, this rebases onto `main`. ## Next in stack PR 4 — `feat(cli)!: rename --template to --example`. Single clean cut, no alias. Tiny PR (~150 lines) that mostly updates `init.ts`'s argument schema, help text, and docs. Depends on this PR so the new flag name can be applied against the refactored code path. 🤖 Generated with [Claude Code](https://claude.com/claude-code) |
||
|
|
69d9f08061 |
refactor: migrate templates/ → registry/examples/ (#253)
## What PR 2/17 of the catalog system rollout. **Physical directory rename.** Stacks on #252. - `git mv templates/ registry/examples/` — all 8 example directories (`decision-tree`, `kinetic-type`, `nyt-graph`, `play-mode`, `product-promo`, `swiss-grid`, `vignelli`, `warm-grain`) plus `templates.json` - `packages/cli/src/templates/remote.ts` — `TEMPLATES_DIR` constant from `"templates"` → `"registry/examples"`, exported for regression testing - `scripts/generate-template-previews.ts` — `remoteTemplatesDir` resolved to the new path - Comment updates in `packages/cli/src/templates/generators.ts` and `packages/cli/src/commands/init.ts` - New regression test `packages/cli/src/templates/remote.test.ts` pinning the path constants so future reverts fail a test instead of silently breaking installed CLIs Design doc: [Hyperframes Catalog System](https://www.notion.so/heygen/Hyperframes-Catalog-System-Design-Plan-341449792c69813f899dcd53b4c0383a). ## Why The current `templates/` directory is a flat "things that scaffold projects" bucket. The catalog model splits content into three tiers: **examples** (full projects — what today's templates are), **blocks** (sub-compositions), and **components** (effect snippets). `registry/examples/` is the canonical home for what was previously at `templates/`, and this PR makes room for `registry/blocks/` and `registry/components/` in future PRs without top-level clutter. ## How - `git mv` preserves file history — GitHub renders these as renames, not deletions + additions. - Remote template fetch via giget reads `TEMPLATES_DIR`, so updating that one constant is sufficient for the CLI's remote code path. - The CLI's **internal** `packages/cli/src/templates/` directory (which holds the `blank` and `_shared` bundled assets plus `generators.ts`/`remote.ts`) is a separate concept and is **not** touched here. Renaming that module belongs to PR 3 where the abstraction changes to a registry resolver. - `templates.json` keeps its existing shape and location (now at `registry/examples/templates.json`). **PR 3 will transform it** to the new `registry.json` shape introduced in PR 1 and generate a per-item `registry-item.json` for each example. Leaving the shape change to PR 3 keeps this PR a pure physical move. ## ⚠️ Breaking change for previously-installed CLIs (`hyperframes@0.1.0` – `0.3.0`) **What happens:** every published CLI version has `TEMPLATES_DIR = "templates"` baked in. After this PR lands on `main`, those CLIs will 404 on: - `raw.githubusercontent.com/heygen-com/hyperframes/main/templates/templates.json` (manifest list) — caught silently in `listRemoteTemplates`, so the template picker falls back to showing only `blank` - `github:heygen-com/hyperframes/templates/<id>#main` (giget download) — raises "Template downloaded but missing index.html" **Decision: accept the break.** Hyperframes is pre-1.0 OSS with a small installed base; complex mitigations (dual-path fetch, redirect stubs, manifest-at-old-path with empty array) add permanent maintenance cost for a one-time rename. **Rollout plan:** 1. Merge #252 (PR 1 — types & schemas) first 2. Merge this PR (#253) 3. Ship a patched CLI release (`hyperframes@0.3.1`) in the same work-day. Already-pinned old CLIs break on remote examples, but upgrading restores full functionality 4. Note the break in release notes + `CHANGELOG.md` under the `0.3.1` entry Users still on an older CLI will see the failure only if they invoke `hyperframes init` with `--template <non-blank>`; `--template blank` (bundled) continues to work offline on every version. ## Test plan - [x] `bun run test` in `packages/cli`: **57 passed** (was 55 on main, +2 regression tests for the path constants). Same 4 pre-existing failures (SRT/VTT whisper normalizer + `lintProject` clean-project test) — unchanged from main. No regressions - [x] **Manual smoke test**: `hyperframes init /tmp/x --template blank` works (bundled code path, unchanged) - [x] `bunx oxfmt --check` + `bunx oxlint`: clean - [x] `bun run typecheck` (core + studio, pre-commit hook): clean - [ ] **Manual smoke test for remote fetch (`--template warm-grain`)** — not verifiable locally before merge. Remote fetch resolves `github:heygen-com/hyperframes/registry/examples/<id>#main`, which doesn't exist until this PR lands. Will work on `main` immediately after merge. ## Breaking / migration - Internal repo path changes only. `--template` CLI flag continues to accept the same template names. - See "Breaking change for previously-installed CLIs" above — decision is to ship a simultaneous CLI release rather than add a compat shim. ## Commits 1. `d691bd1` — initial rename + CLI path constant update 2. `fc0c642` — review feedback: docstring fix, regression tests, clarifying comment in `init.ts`, export constants for testing ## Stacks on #252 — base branch. When #252 merges, this rebases onto `main`. ## Next in stack PR 3 — `feat(cli): registry resolver + installer`. Transforms `templates.json` to the new `registry.json` shape (from PR 1's schema), generates `registry-item.json` for every existing example, introduces `packages/cli/src/registry/{resolver,installer,remote}.ts`, renames the `packages/cli/src/templates/` CLI module, and refactors `init` to call through the new abstraction. 🤖 Generated with [Claude Code](https://claude.com/claude-code) |