- Fix project skill directory to .agents/skills/ (plural) in both guides,
matching vercel-labs/skills agent registry
- Replace invented --mcp-server flag with correct --additional-mcp-config
flag and JSON/file syntax for Copilot CLI
- Remove non-existent /skills reload, /skills list, /skills info commands;
document only /skills (picker) and /skills add
- Remove non-existent github-copilot binary alias
- Antigravity MCP section now defers to Antigravity's own MCP docs for
the exact settings UI path
- Rename CLAUDE.md section to "Agent instruction files", document both
AGENTS.md (cross-agent) and CLAUDE.md
- Use --agent long form instead of -a in examples
- Add link to Antigravity Manager view docs
- Add token budget caveat for large skill sets in Copilot CLI
Add dedicated guide pages for two AI coding tools that were missing
from the documentation (closes#744):
- docs/guides/antigravity.mdx — skills install, semantic matching,
Manager view parallelism, MCP alternative, CLAUDE.md compat
- docs/guides/copilot-cli.mdx — skills install, slash commands,
/skills management, agent mode, MCP alternative
Also updates quickstart.mdx and prompting.mdx to mention both tools
alongside the existing agent list, and adds both pages to the docs
navigation in docs.json.
Move the 7-step production pipeline (Capture → Design → Script → Storyboard
→ VO + Timing → Build → Validate) into its own dedicated guide so it serves
any Hyperframes project, not just website-to-video. Expand each step with
file contents, project layout, gates, and iteration patterns. Reference the
new page from website-to-video, quickstart, prompting, and launch-videos.
The Preview Shortcuts section was missing the shortcuts shipped in #710
and #811: J/K/L shuttle, I/O work-area markers with A/E jumps, the
Cmd/Ctrl+Scroll preview zoom-at-cursor, and undo/redo. The arrow-key
entries were also wrong — they step by frames, not seconds.
Reorganise the table into the same groups the in-app `⌨` panel uses
(Playback, Work area, View, Application) and source each row from
`usePlaybackKeyboard.ts`, `useAppHotkeys.ts`, and the `NLEPreview` wheel
handler so the doc tracks what the Studio actually does. Mention that
the loop respects the work area when in/out are set, per #811.
Closes#812
The producer already supports `format: "png-sequence"` end-to-end (see
RenderConfig in renderOrchestrator.ts), but the CLI's VALID_FORMAT
validator rejects it before the flag reaches the producer. Surface it
the same way `mov` and `webm` are surfaced.
Behaviour:
- `--format png-sequence` accepted alongside mp4/webm/mov.
- Auto-output path uses no extension (FORMAT_EXT["png-sequence"] = "")
since the producer treats outputPath as a directory of frame_NNNNNN.png.
- `printRenderComplete` sums the contained file sizes when outputPath
is a directory, instead of reporting the platform-dependent inode
size.
- DockerRenderOptions.format type extended; existing buildDockerRunArgs
is unchanged because it forwards the string verbatim.
Tests:
- renderLocal forwards `format: "png-sequence"` to createRenderJob.
- buildDockerRunArgs propagates `--format png-sequence` to the
container.
Docs:
- Rendering guide: format flag table, format comparison table, new
"PNG sequence (no encoding)" section, "How it works" extended.
- CLI package docs: format flag table updated.
Remove dollar amounts, render-time figures, and credit allowances from the
Vercel/Cloudflare tabs. These were sourced from the template READMEs but go
stale fast (pricing changes) and are load-bearing on a single composition's
quirks (perf isn't proportional to duration). Keep qualitative framing and
link out to the canonical pricing pages instead.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Reword frontmatter description to describe capability, not providers
- Soften "deploy in one click" — Cloudflare requires Workers Paid plan
- Qualify Cloudflare ~25s perf number as a local-Docker measurement
on a 6-vCPU host, not a standard-4 production figure
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Surfaces the two official one-click deployment templates
(heygen-com/hyperframes-vercel-template, heygen-com/hyperframes-cloudflare-template)
in the docs site. Previously they only existed as GitHub READMEs.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* 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.
Emit an inverse-alpha background plate alongside the cutout in a single
inference pass. Same source RGB, alpha = 255 − mask. Dual-encoder pipeline
runs in parallel; both outputs share the same --quality preset.
This is a hole-cut plate (subject region transparent), not an inpainted
clean plate — composite something opaque under it to fill the hole.
Docs and skill cover when each is the right tool.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The model removes background from any video with a person — we tested
with avatars because they were convenient, but anyone can bring a
talking-head clip, presenter footage, vlog, etc. Replace avatar-specific
filenames (avatar.mp4 / brandon.mp4) with neutral subject.mp4 (or
presenter.mp4 in the text-behind-subject example) and rephrase
copy that read as if avatars were the only use case.
Touches docs/guides/remove-background.mdx, hyperframes-media SKILL.md,
and hyperframes/patterns.md.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Skill (hyperframes-cli): three-pattern table (cutout-over-different-scene
vs over-its-own-source vs over-different-take) + the two non-obvious rules
(wrap video in non-timed div for opacity control, both videos data-start=0
for sync). Skill (hyperframes/patterns): worked text-behind-subject example.
Docs: --quality flag, compositing pitfalls section, quality preset table.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Move tts/transcribe/remove-background guidance into a new
hyperframes-media sibling skill so the CLI skill stays focused on
the dev loop (init/lint/inspect/preview/render/doctor).
Two motivations:
1. Description bloat. The CLI skill listed every subcommand as a
trigger keyword, which made agents auto-load it for any mention
of audio, transcription, or backgrounds — even when the task
was just rendering a composition.
2. Body bloat. Voice tables, the .en-translates-non-English
whisper rule, and codec selection guidance all loaded on
every CLI invocation. With three preprocessing commands now
in the CLI (tts, transcribe, remove-background), this is only
going to grow.
The split keeps a single sibling (hyperframes-media), not three:
the commands share a workflow (preprocess asset → drop into
composition) and the same first-run-downloads-a-model pattern,
so they belong together. CLI skill now references hyperframes-media
from a one-paragraph "Asset Preprocessing" stub.
Doc references updated in README.md, CLAUDE.md,
docs/quickstart.mdx, and docs/guides/prompting.mdx.
Adds `hyperframes remove-background` — a local-AI subcommand that mattes a
video or image with the u2net_human_seg ONNX model and emits a transparent
WebM (VP9-alpha), ProRes 4444 .mov, or RGBA PNG. Drops directly into any
composition's <video> tag — no green screen, no API keys, no upload.
Auto-picks the fastest available execution provider via onnxruntime-node:
CoreML on Apple Silicon, CUDA when HYPERFRAMES_CUDA=1, CPU otherwise.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add a parallel handoff path for users of [Open Design](https://github.com/nexu-io/open-design),
the Apache-2.0, local-first, BYOK alternative to Claude Design that drives whichever
coding-agent CLI the user already has on their PATH (Claude Code, Codex, Cursor, Gemini,
OpenCode, Qwen, Copilot, Hermes, Kimi, Pi).
Mirrors the existing Claude Design integration:
- README: a paragraph next to the Claude Design one, pointing at the new guide and
explaining the drop-into-skills/SKILL.md install path
- docs/guides/open-design.mdx: Mintlify page parallel to claude-design.mdx, with
Steps, comparison table, prompts, limitations, handoff
- docs/guides/open-design-hyperframes.md: SKILL.md-shaped instruction file users
drop into skills/hyperframes-handoff/SKILL.md (Open Design auto-discovers it
on next request) or attach to chat as a one-shot
- docs/docs.json: nav entry for the new page
The instruction file deliberately defers to claude-design-hyperframes.md as the
canonical reference for skeleton catalogs, shader patterns, HDR, and audio-reactive
animation — it stays focused on what Open Design's prompt stack needs at emission
time (active-DESIGN.md binding, 5-dim self-critique gate, structural rules) so the
two guides don't drift.
Open Design already ships a motion-frames skill that says "hand-off ready for
HyperFrames" — this PR closes the loop on the HyperFrames side so the route is
discoverable from the HyperFrames docs.
Co-authored-by: pftom <huan1043269996@gmail.com>
## Problem
HyperFrames already had `--gpu`, but that flag only controlled FFmpeg hardware encoding. The browser capture path still forced Chrome/WebGL through SwiftShader software GL via `--use-angle=swiftshader`, so WebGL-heavy local renders could leave the biggest bottleneck on the CPU path.
That made the existing flag naming easy to misread: `--gpu` sounded like it accelerated the whole render, but it did not change the browser frame-capture backend.
## What this fixes
- Enables host browser GPU acceleration automatically for local CLI renders.
- Adds `--no-browser-gpu` as the local opt-out for software Chrome/WebGL capture.
- Keeps `--browser-gpu` as an explicit local browser-GPU request.
- Adds `browserGpuMode: "software" | "hardware"` to engine config, with `PRODUCER_BROWSER_GPU_MODE` env support for lower-level producer users.
- Keeps Docker browser capture on the deterministic software path.
- Maps hardware browser GPU mode to platform-native Chrome backends:
- macOS: Metal-backed ANGLE
- Windows: D3D11-backed ANGLE
- Linux: EGL
- Blocks explicit `--browser-gpu --docker` with a clear error because Docker browser GPU passthrough is not cross-platform.
- Clarifies docs so `--gpu` means FFmpeg encoder GPU and browser GPU means Chrome/WebGL capture GPU.
- Keeps encoder backend selection auto-detected from FFmpeg capabilities:
- NVIDIA: NVENC
- macOS: VideoToolbox
- Linux: VAAPI
- Intel: QSV
## Why two flags
There are two separate GPU surfaces in the render pipeline:
1. Browser GPU controls Chrome frame capture.
- Affects WebGL, canvas, CSS rendering, compositing, and screenshot capture inside the browser.
- This is enabled automatically for local CLI renders.
- Use `--no-browser-gpu` when you want the software browser baseline.
2. `--gpu` controls FFmpeg video encoding.
- Affects the final encode step after frames have already been captured.
- The concrete encoder is auto-detected from the host FFmpeg build and hardware.
- It can be faster for some machines/codecs, but it is not equivalent to browser rendering acceleration.
The controls stay independent because users may want:
- `hyperframes render` for the fast local default with browser GPU capture.
- `hyperframes render --no-browser-gpu` for the software-browser local baseline.
- `hyperframes render --gpu` for browser GPU capture plus hardware FFmpeg encoding.
- `hyperframes render --no-browser-gpu --gpu` for software browser capture plus hardware FFmpeg encoding.
- `hyperframes render --docker` for deterministic browser capture.
## Why `--gpu` does not imply browser GPU
Keeping `--gpu` scoped to FFmpeg encoding avoids a semantic break and keeps the risk profile explicit:
- `--gpu` already means encoder acceleration. Expanding it to also change Chrome capture would silently alter behavior for users who only wanted hardware encoding.
- Browser GPU and encoder GPU have different portability. Encoder GPU can work in Docker when the host exposes the right devices; browser GPU passthrough is not cross-platform, so this PR intentionally blocks explicit `--browser-gpu --docker`.
- The Apple presentation benchmark shows why the controls should stay separate: browser GPU capture was the useful improvement, while macOS VideoToolbox via `--gpu` was slower and produced larger output for this `standard` H.264 run.
If HyperFrames later wants a single umbrella acceleration control, it should be explicit, for example `--acceleration browser|encoder|all` or `--gpu=browser|encoder|all`, rather than changing the meaning of the existing boolean `--gpu`.
## Root cause
`buildChromeArgs()` always injected `--use-gl=angle --use-angle=swiftshader`. `disableGpu` only appended `--disable-gpu`; it did not provide a hardware-GPU mode. That made the public `--gpu` flag look broader than it was, because render capture stayed software-backed even when encoder GPU was requested.
## Verification
### Local checks
- `bun install`
- `bun run build:hyperframes-runtime`
- `bun run --filter @hyperframes/engine test src/config.test.ts src/services/browserManager.test.ts`
- `bun run --filter @hyperframes/cli test src/utils/dockerRunArgs.test.ts src/commands/render.test.ts`
- `bun run --filter @hyperframes/cli typecheck`
- `bun run --filter @hyperframes/engine typecheck`
- `bun run --filter @hyperframes/producer typecheck`
- `cd packages/producer && bunx vitest run src/services/renderOrchestrator.test.ts`
- `bunx oxlint packages/cli/src/commands/render.ts packages/cli/src/commands/render.test.ts packages/cli/src/utils/dockerRunArgs.ts packages/cli/src/utils/dockerRunArgs.test.ts packages/engine/src/config.ts packages/engine/src/config.test.ts packages/engine/src/services/browserManager.ts packages/engine/src/services/browserManager.test.ts packages/producer/src/services/renderOrchestrator.test.ts`
- `bunx oxfmt --check ...` on changed source/docs files
- `git diff --check`
- `bun packages/cli/src/cli.ts render --help | rg -n "browser-gpu|no-browser-gpu|GPU"`
- `bun packages/cli/src/cli.ts render packages/producer/tests/css-spinner-render-compat/src --output /tmp/hf-auto-browser-gpu-smoke.mp4 --workers 1 --quality draft --fps 24 --strict`
- Render plan prints `GPU: browser GPU (auto)`.
- `bun packages/cli/src/cli.ts render packages/producer/tests/css-spinner-render-compat/src --no-browser-gpu --output /tmp/hf-software-browser-gpu-smoke.mp4 --workers 1 --quality draft --fps 24 --strict`
- Render plan does not print browser GPU.
- `bun packages/cli/src/cli.ts render packages/producer/tests/css-spinner-render-compat/src --docker --browser-gpu --output /tmp/should-not-render.mp4`
- Exits 1 with `Browser GPU is local-only`.
- `buildDockerRunArgs()` regression coverage asserts Docker container args include `--no-browser-gpu`, preventing nested container renders from re-enabling browser GPU through the local CLI default.
- `resolveBrowserGpuForCli()` regression coverage asserts `PRODUCER_BROWSER_GPU_MODE=software` opts out when no CLI browser-GPU flag is supplied, while explicit `--browser-gpu` / `--no-browser-gpu` still win.
- `ffmpeg -v error -i /tmp/hf-auto-browser-gpu-smoke.mp4 -f null -`
- `ffmpeg -v error -i /tmp/hf-software-browser-gpu-smoke.mp4 -f null -`
- `ffprobe -v error -show_entries format=duration:stream=codec_name,width,height,r_frame_rate -of json /tmp/hf-browser-gpu-smoke.mp4` -> H.264, 1920x1080, 24fps, 5.0s
### Apple presentation benchmark
Rendered `/Users/miguel07code/Downloads/apple-presentation.zip` as supplied after extracting to `/tmp/hf-apple-profile/apple-presentation`.
Fixed settings:
- 1920x1080
- 30fps
- `standard` quality
- 4240 frames
- 141.32s duration
- 8-worker cap; render auto-calibration used 6 capture workers
- macOS host detected FFmpeg GPU encoder: `videotoolbox`
| Mode | Equivalent flags after this PR | Wall time | vs software-browser baseline | Speed | Capture | Encode | Output |
| --- | --- | ---: | ---: | ---: | ---: | ---: | ---: |
| Software browser + CPU encode | `--no-browser-gpu` | 120.77s | baseline | 1.17x | 97.87s | 10.04s | 8.38MB |
| Browser GPU + CPU encode | default local render | 70.10s | 42.0% faster | 2.02x | 50.72s | 9.91s | 8.39MB |
| Software browser + encoder GPU | `--no-browser-gpu --gpu` | 133.16s | 10.3% slower | 1.06x | 103.58s | 18.31s | 25.43MB |
| Browser GPU + encoder GPU | `--gpu` | 74.12s | 38.6% faster | 1.91x | 46.69s | 17.93s | 25.45MB |
Result: browser GPU capture is the meaningful improvement for this WebGL/browser-capture-heavy presentation. VideoToolbox encoding was slower and produced larger files for this current `standard` H.264 path, so `--gpu` should stay separate and opt-in.
Why `--gpu` plus browser GPU was slower than browser GPU alone: the combined run captured about 4.0s faster than browser GPU alone, but VideoToolbox encoding was about 8.0s slower than CPU x264 encoding, so the encode loss outweighed the capture gain.
### VideoToolbox flag check
I also isolated the encode stage against the already-captured Apple frames to check whether macOS GPU encoding only needed special flags.
`ffmpeg -h encoder=h264_videotoolbox` does not expose a CRF/CQ-style quality option like x264. It exposes bitrate-oriented and VideoToolbox-specific options such as `-b:v`, `-realtime`, `-profile`, `-coder`, `-prio_speed`, `-power_efficient`, and `-allow_sw`. That means our current `-q:v` mapping is not equivalent to x264 CRF and can produce very different bitrate/size behavior.
Measured full-frame encode variants on this host:
| VideoToolbox variant | Encode wall time | Output size | Bitrate |
| --- | ---: | ---: | ---: |
| Current `-q:v 64 -allow_sw 1` | 18.76s | 25.31MB | 1.43 Mbps |
| Current without `-allow_sw 1` | 18.21s | 25.31MB | 1.43 Mbps |
| `-b:v 500k -maxrate 750k -bufsize 1000k -profile high -coder cabac -realtime 1 -prio_speed 1 -power_efficient 0` | 20.58s | 7.42MB | 0.42 Mbps |
| Same with `-b:v 1500k` | 20.84s | 16.70MB | 0.95 Mbps |
| `-b:v 500k -profile baseline -coder cavlc -realtime 1 -prio_speed 1 -power_efficient 0` | 18.11s | 8.94MB | 0.51 Mbps |
Conclusion: VideoToolbox can be made size/bitrate-predictable with explicit `--video-bitrate`, but the tested speed-oriented flags did not make it faster than CPU x264 wall time for this render. That reinforces keeping `--gpu` encoder acceleration explicit and separate from browser GPU capture.
Artifacts from the local benchmark:
- `/tmp/hf-apple-profile/results/cpu.mp4`
- `/tmp/hf-apple-profile/results/browser-gpu.mp4`
- `/tmp/hf-apple-profile/results/encoder-gpu.mp4`
- `/tmp/hf-apple-profile/results/full-gpu.mp4`
- `/tmp/hf-apple-profile/results/summary.json`
All four benchmark MP4s completed `ffprobe` and full `ffmpeg -f null` decode checks.
### Pixel comparison
Compared decoded MP4 output between software-browser and browser-GPU renders:
- Apple presentation:
- 4240 frames compared
- 636 exact matching decoded frame hashes
- 3604 different decoded frame hashes
- Average PSNR: 57.79 dB
- `css-spinner-render-compat` clean fixture:
- 120 frames compared
- 0 exact matching decoded frame hashes
- Average PSNR: 61.57 dB
Interpretation: browser GPU output is not strict hash/pixel-identical to the software-browser path after lossy H.264 encode, but the measured deltas are visually tiny. Above 50 dB PSNR is typically visually indistinguishable for normal video review. Use `--no-browser-gpu` or Docker when strict cross-run/cross-machine reproducibility matters more than local speed.
### Browser verification
- Started HyperFrames Studio preview for `packages/producer/tests/css-spinner-render-compat/src`.
- Used `agent-browser` to open `http://localhost:5191#project/src` and verify the composition loaded in Studio.
- Screenshots:
- `/tmp/hf-gpu-browser-proof/preview-loaded.png`
- `/tmp/hf-gpu-browser-proof/preview-playing.png`
- `/tmp/hf-gpu-browser-proof/preview-frame-60.png`
- Agent-browser recordings:
- `/tmp/hf-gpu-browser-proof/preview-playback.webm`
- `/tmp/hf-gpu-browser-proof/preview-seek.webm`
## Notes
- Browser GPU is enabled automatically for local CLI renders and disabled in Docker.
- `--no-browser-gpu` is the opt-out for software Chrome/WebGL capture.
- `--gpu` remains encoder-only and opt-in.
- The Apple presentation zip has existing lint errors around unmanaged nested videos and imperative media `play()` calls. The benchmark still compares the same supplied source across modes, but it should not be treated as a clean deterministic-composition fixture.
Adds a hardlinkable doc at /guides/mcp covering setup, available
tools, prompting tips, and debugging for the HyperFrames MCP.
Not added to docs.json navigation yet — accessible via direct URL
only until the MCP launches.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(render): auto-detect HDR from media probes, add --sdr flag
Replace the --hdr opt-in model with automatic detection. When no flags
are passed, the renderer probes all video/image sources and enables HDR
output if any HDR color space is detected. Existing --hdr flag becomes
a force override. New --sdr flag forces SDR output.
Behavior matrix:
(no flags) + HDR content → HDR output
(no flags) + SDR content → SDR output
--hdr → force HDR (defaults to HLG if no HDR sources)
--sdr → force SDR (skips probing)
--hdr --sdr → error
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: align HDR auto-detect docs and tests
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fast reference for non-technical video editors and creatives — covers the
fast loop, terminal shortcuts, Studio keyboard shortcuts, CLI commands,
timing attributes, render presets, publish/share, and quick fixes.
- Link to claude.ai/design instead of claude.ai
- Remove raw.githubusercontent download links (just GitHub with ↓ button)
- Fix stale SKILL.md link text in prompting guide
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add dynamic resolution to shader transitions and update Skeleton A
to use shaders on vertical compositions.
shader-transitions changes:
- webgl.ts: read dimensions from params instead of hardcoded constants
- capture.ts: accept width/height for html2canvas
- hyper-shader.ts: read data-width/data-height from composition root
skill + docs changes:
- Skeleton A now has 1 shader at hero reveal (s3→s4 midpoint)
- Removed "no shaders on vertical" limitation from docs
- Updated claude-design.mdx known limitations section
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Raw GitHub URLs serve as text/plain — clicking opens a text tab
instead of downloading. Updated all 5 references across 4 files:
- claude-design.mdx (2 refs): "right-click → Save Link As"
- prompting.mdx (1 ref): "right-click → Save Link As"
- README.md (1 ref): "click download button on GitHub"
- quickstart.mdx (1 ref): "click download button on GitHub"
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Update docs, quickstart, prompting guide, and README to reflect:
- Template-first approach (attach file, not paste URL)
- Claude Design produces drafts, refine in any AI coding agent
- Known limitations (vertical shaders, seeking, no linting)
- Practical example prompts (feature announcement, founder pitch)
- Removed outdated references (invisible bridges, fetch-the-skills-tree)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## Summary
- add a GitHub-hosted `claude-design-hyperframes` skill entry point that tells Claude Design to fetch the upstream HyperFrames skills tree
- add a dedicated Claude Design docs guide and link it from quickstart, prompting, and the README
- fix `@hyperframes/player` CDN docs to show a working ESM include and the explicit global-build fallback
## Verification
- `bunx oxfmt --check README.md docs/docs.json docs/guides/prompting.mdx docs/packages/player.mdx docs/quickstart.mdx packages/player/README.md docs/guides/claude-design.mdx skills/claude-design-hyperframes/SKILL.md`
- `bun run lint:skills`
- `bunx mintlify broken-links`
- browser-engine screenshots captured with Playwright CLI for the changed docs/source surfaces:
- `/tmp/hyperframes-pr-artifacts/claude-design-guide-source.png`
- `/tmp/hyperframes-pr-artifacts/player-docs-source.png`
## Notes
- `mintlify dev`, `mintlify validate`, and `mintlify export` stalled in this environment during preview/bootstrap, so I used the broken-links check plus screenshot-based browser fallback instead of claiming a full rendered-site pass.
- The GitHub entry-point setup reflects current Claude Design behavior discussed in the task: point Claude Design at the repo-hosted skill URL rather than a ZIP upload flow.
## Summary
Three independent fixes that share a common thread: HDR config flowing correctly from `EngineConfig` down through every encoder. The headline fix: disk-based HDR encodes via `chunkEncoder` were silently producing BT.709-tagged output despite `options.hdr` being set.
## Why
`Chunk 3` of `plans/hdr-followups.md`. The streaming encoder was correct but `chunkEncoder.buildEncoderArgs` hard-coded BT.709 color tags and the `bt709` VUI block in `-x265-params`, even when callers passed an HDR `EncoderOptions`. Today this is harmless because `renderOrchestrator` routes native-HDR content to `streamingEncoder` and only feeds `chunkEncoder` sRGB Chrome screenshots — but the contract was a lie, and any future caller that wired HDR through `chunkEncoder` would silently get SDR output.
## What changed
**3A — `chunkEncoder` respects `options.hdr` (BT.2020 + mastering metadata).** When `options.hdr` is set, the libx265 software path emits `bt2020nc` plus the matching transfer (`smpte2084` for PQ, `arib-std-b67` for HLG) at the codec level *and* embeds master-display + max-cll SEI in `-x265-params` via `getHdrEncoderColorParams`. libx264 still tags BT.709 inside `-x264-params` (libx264 has no HDR support) but the codec-level color flags flip so the container describes pixels truthfully. GPU H.265 (nvenc/videotoolbox/qsv/vaapi) gets the BT.2020 tags but no `-x265-params` block, so static mastering metadata is omitted — acceptable for previews, not HDR-aware delivery.
**3B — `convertSdrToHdr` accepts a target transfer.** `videoFrameExtractor.convertSdrToHdr` was hard-coded to `transfer=arib-std-b67` (HLG) regardless of the surrounding composition's dominant transfer. `extractAllVideoFrames` now calls `analyzeCompositionHdr` first, then passes the dominant transfer (`"pq"` or `"hlg"`) into `convertSdrToHdr` so an SDR clip mixed into a PQ timeline gets converted with `smpte2084`, not `arib-std-b67`.
**3C — `EngineConfig.hdr` type matches its declared shape.** The IIFE for the `hdr` field returned `undefined` when `PRODUCER_HDR_TRANSFER` wasn't `"hlg"` or `"pq"`, but the field is typed as `{ transfer: HdrTransfer } | false`. Returning `false` matches the type and avoids a downstream `undefined` check.
## Test plan
- [x] `chunkEncoder.test.ts`: replaced the previous "HDR options ignored" assertions with 8 new specs covering BT.2020 + transfer tagging, master-display/max-cll embedding, libx264 fallback behavior, GPU H.265 + HDR (tags but no x265-params), and range conversion for both SDR and HDR CPU paths.
- [x] All 313 engine unit tests pass (5 new HDR specs).
- [x] `ffprobe` an HDR composition rendered through the chunk encoder path: shows `bt2020nc` color matrix, `smpte2084` transfer, and mastering display metadata.
## Stack
Chunk 3 of `plans/hdr-followups.md`. Independent of Chunks 1/4 (touches separate code paths).
## Summary
- hide the leading trim handle for timeline clips that cannot offset their own content
- keep leading trim available for media clips backed by playback offset metadata or source duration
- map visual row priority like a normal timeline editor: top timeline rows render above lower rows
## Why This Is Needed
Generic GSAP/DOM timeline clips do not have a playback-offset model like media clips do.
That means a left trim affordance on those clips is misleading today:
- users reasonably expect front trim to remove the beginning of the animation
- the current model can only shorten the clip window, not start the motion halfway through
Instead of exposing a control that implies unsupported behavior, this PR keeps true front trim only on clips that can actually offset their content.
The PR also fixes the stacking convention so the timeline matches normal editor expectations:
- visually higher track row = higher render priority
- visually lower track row = lower render priority
## Current Flow By Element Type
### Generic motion / DOM clips
Examples: `section`, `div`, `aside`, GSAP-driven cards and overlays.
Current supported flow:
- drag the whole clip horizontally to change `data-start`
- right-trim to shorten the end of the clip window
- move between tracks to change `data-track-index`
Not supported yet:
- true front trim that removes the beginning of the animation itself
Behavior after this PR:
- no interactive left trim handle is shown
- right trim still works
- horizontal move still works
### Media clips
Examples: `video` / `audio` clips, or wrappers carrying `data-media-start` / `data-playback-start`.
Current supported flow:
- drag the whole clip horizontally to change `data-start`
- left trim advances clip start and playback offset together
- right trim shortens `data-duration`
Behavior after this PR:
- both left and right trim handles remain available
- left trim persists `data-start` plus `data-media-start` / `data-playback-start`
- right trim persists `data-duration`
## Z-Index Rule
This PR now follows the normal timeline-editor convention:
- top visual row on the timeline = highest `z-index`
- lower visual rows = lower `z-index`
Concretely, because Studio renders tracks in ascending numeric order from top to bottom, lower numeric track values now map to higher `z-index` values.
## Validation
### Automated
- `bun test packages/studio/src/player/components/timelineEditing.test.ts packages/studio/src/player/components/Timeline.test.ts packages/studio/src/player/store/playerStore.test.ts packages/studio/src/utils/sourcePatcher.test.ts`
- `bun run --filter @hyperframes/studio typecheck`
### Browser verification
Verified with `agent-browser` on `timeline-edit-playground`:
- generic motion clips no longer expose an interactive left trim handle
- media clips still expose both trim handles
- left trim on `media-card` persisted `data-start` and `data-media-start`
- right trim on `media-card` persisted `data-duration` only
- moving `title-card` from the bottom row to the top row persisted the highest `z-index` for the top-row clips
- recordings:
- `/tmp/trim-fix-artifacts/trim-flow.webm`
- `/tmp/trim-fix-artifacts/z-index-flow.webm`
Adds honest Hyperframes vs Remotion comparison: README section with
paragraph + table + open-source-vs-source-available callout, plus a
full guide at docs/guides/hyperframes-vs-remotion.mdx walking through
the core React-vs-HTML decision, practical differences (including a
GSAP side-by-side), and licensing.
Closes#318
## Summary
This PR ended up covering the full HDR Docker/docs follow-through plus the producer/engine work needed to make HDR still images render and regress correctly in CI.
The branch now does four things:
- forwards `--hdr` through the Docker render path in the CLI
- adds and expands HDR documentation across the docs site
- adds first-class HDR still-image support to the engine/producer pipeline
- adds targeted HDR regression coverage, including a CI-safe fallback for PNG HDR metadata detection when `ffprobe` does not expose PNG color tags
## What changed
### CLI and docs
- `hyperframes render --docker --hdr` now preserves `--hdr` when invoking the in-container CLI
- added a dedicated HDR guide and linked it from CLI, producer, engine, rendering, and common-mistakes docs
- documented HDR constraints and verification flow: HDR source requirements, MP4/H.265 Main10 output, PQ/HLG handling, Docker usage, and common SDR fallback causes
### Engine and producer HDR image support
- added `ImageElement` support to the engine composition model and parsing path
- threaded image elements through producer compilation and orchestration
- probed image sources for HDR color spaces so image-only compositions can trigger HDR output without requiring an HDR video source
- included HDR image start times in stacking queries so the layered compositor can place images correctly in z-order
- integrated HDR image compositing into the layered HDR render loop alongside native HDR video layers and SDR DOM overlays
- forced screenshot mode for HDR layered compositing where required to keep DOM/HDR layer composition deterministic
- skipped readiness waiting for natively extracted HDR videos in the engine path where it was unnecessary and could block layered HDR flows
### HDR metadata robustness
- added a fallback in `extractVideoMetadata()` to read PNG `cICP` metadata directly when `ffprobe` omits color-space fields for PNGs
- this specifically fixes CI/Docker detection for the `hdr-image-only` fixture, where the render was falling back to SDR because the PNG was not being recognized as BT.2020 PQ
### Regression coverage and fixture cleanup
- added `hdr-image-only`, a regression fixture that validates HDR still-image rendering end to end
- added `hdr-pq`, a focused HDR PQ regression fixture for the video path
- updated regression CI to run an `hdr` shard with `--sequential hdr-pq hdr-image-only`
- removed the older larger `hdr-regression/*` fixture set in favor of the smaller targeted regressions used by CI
- added the necessary fixture generation/readme material and checked-in golden outputs for the new HDR tests
## Why
The original PR description only covered the CLI flag forwarding and docs work. Since then, the branch also picked up the missing runtime support needed for HDR still images and the regression coverage to keep that path from breaking.
The practical issue this closes is:
- local host runs could pass while CI failed `hdr-image-only`
- the failure was a full-frame visual mismatch caused by SDR fallback, not unstable rendering
- root cause was PNG HDR metadata not being surfaced by `ffprobe` in the CI Docker environment
- parsing the PNG `cICP` chunk directly makes HDR detection deterministic across environments
## Test plan
### Local targeted checks
```bash
bunx oxlint packages/engine/src/utils/ffprobe.ts packages/engine/src/utils/ffprobe.test.ts
bunx oxfmt packages/engine/src/utils/ffprobe.ts packages/engine/src/utils/ffprobe.test.ts
bun --cwd packages/engine test src/utils/ffprobe.test.ts src/utils/hdr.test.ts
```
### Producer regression runs on host
```bash
bun run --cwd packages/core build:hyperframes-runtime:modular
bun --cwd packages/producer test -- --sequential --exclude-tags slow,render-compat,hdr
bun --cwd packages/producer test -- --sequential hdr-pq hdr-image-only
```
Observed result:
- `fast` shard: 7 passed, 0 failed
- `hdr` shard: 2 passed, 0 failed
### CI-equivalent Docker verification
```bash
docker build -f Dockerfile.test -t hyperframes-producer:test .
docker run --rm \
--security-opt seccomp=unconfined \
--shm-size=4g \
-v "$PWD/packages/producer/tests:/app/packages/producer/tests" \
hyperframes-producer:test \
--sequential hdr-pq hdr-image-only
```
Observed result:
- `hdr-image-only`: passed
- `hdr-pq`: passed
- shard summary: 2 passed, 0 failed
### Specific regression fixed
Before the PNG `cICP` fallback, the Docker/CI run failed `hdr-image-only` with:
- missing `"[Render] HDR source detected — output: PQ ..."` log line
- full-frame visual mismatch across all 100 checkpoints
- PSNR ~17 on every frame, indicating a consistent SDR-vs-HDR pipeline mismatch
After the fallback, the same Docker path recognizes the PNG as HDR and the shard passes.
* refactor(engine): restructure frame reorder buffer with Map-keyed storage
Rewrites createFrameReorderBuffer to use a Map<number, Array<() => void>>
keyed by frame index instead of a flat Array<{frame, resolve}> scanned on
every advance. O(1) lookups in enqueue/flush, fast-paths for the matching-
cursor and overshoot cases, and a small fix: waitForAllDone now coexists
with the writer still waiting on the final frame instead of colliding on
the same waiter slot.
Also adds 5 unit tests (there were none before) covering the fast-path,
out-of-order gating, multi-waiter-per-frame semantics, waitForAllDone
normal path, and the overshoot case.
Comment tweaks on buildChromeArgs — the flag profile is the standard
headless-for-capture set (Puppeteer / Playwright / Chrome headless-shell
all converge on similar flags); rephrased for clarity.
* refactor(cli): simplify port availability probe with async/await
Rewrites isPortAvailableOnHost from a single new-Promise callback into an
async/await form with an intermediate `bindError: ErrnoException | null`
variable. Makes the bind-then-release flow explicit as two sequential
awaits, and broadens the non-EADDRINUSE errno commentary (EADDRNOTAVAIL
for disabled IPv6, EACCES for privileged ports, EAFNOSUPPORT for missing
address families — all treated as "this host doesn't apply", not "port
occupied").
No behavior change to existing callers; all four portUtils tests still
pass.
* docs: add CREDITS.md and surface website-to-hyperframes skill
- New CREDITS.md acknowledging prior art in the browser-based video
rendering space (Remotion) and the ecosystem HyperFrames builds on
(Puppeteer, FFmpeg, GSAP, Hono). Standard OSS practice.
- Adds the `website-to-hyperframes` skill to the skills tables in
README.md, docs/guides/prompting.mdx, and the project template at
packages/cli/src/templates/_shared/CLAUDE.md. The skill ships in
skills/ but was missing from every table.
- Adds `/hyperframes-registry` to the prose mention in the repo
CLAUDE.md.
* docs(guides): add performance guide and preview-stutter troubleshooting
Adds a dedicated Performance guide covering preview-vs-render cost model,
expensive CSS patterns (backdrop-filter, filter, shadows), image sizing,
and how to diagnose slow compositions with Chrome DevTools.
Cross-links from troubleshooting (new "Preview stutters" accordion) and
common-mistakes (new "Oversized source images" and "Heavy backdrop-filter
stacks" accordions). Wires the new page into docs.json nav.
Also fixes a pre-commit format hook edge case: oxfmt would exit 2 when
the only staged files matching the format glob were all covered by
.prettierignore (e.g. docs-only changes). Add --no-error-on-unmatched-pattern
to the lefthook oxfmt invocation so docs-only commits are not blocked.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* docs: call out preview performance limits at the entry points
The preview command, studio package, and determinism concept pages all
frame preview as visually equivalent to render — correct for fidelity,
misleading for playback smoothness. A user who reads those pages and
then hits a paint-heavy composition has no way to know why preview
stutters, short of drilling into troubleshooting.
Adds short notes at each entry point linking out to the new Performance
guide, so users hit the "preview is hardware-bound, render isn't"
explanation wherever they land first.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Raise default encoding quality to visually lossless at 1080p (CRF 18)
and expose fine-grained encoding controls for power users.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: add prompt cookbook + prompting guide for AI agents
Addresses user feedback that there's no guidance on how to actually
prompt Claude Code (or other agents) once the hyperframes skills are
installed. Adds copy-pasteable example prompts in the README and
quickstart, a new prompting guide page, and a starter-prompt nudge in
the `hyperframes init` output.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs(prompting): add vocabulary tables, rules, and TTS voice guide
Merges the best content from the internal prompt guide into
prompting.mdx: easing vocabulary, caption tone table, transition
energy matrix, audio-reactive frequency mapping, marker highlight
modes, TTS voice recommendations, rendering quality presets, and
framework rules (technical requirements vs best practices).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs(prompting): rename page title to "Prompt Guide"
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: remove greensock/gsap-skills dependency, fix Math.random nuance
The bundled skills/gsap/ already covers the GSAP surface needed for
HyperFrames compositions. Installing greensock/gsap-skills on top adds
a competing full-ecosystem skill that's mostly irrelevant (ScrollTrigger,
Draggable, SplitText, etc.) and can confuse agents about which GSAP
context to load.
Also adds seeded-PRNG nuance to the Math.random() rule in the prompt
guide (matching the skill's actual guidance).
Removed from: skills.ts, README, AGENTS.md, shared AGENTS.md/CLAUDE.md,
and prompting.mdx.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* chore: require minimal reproduction link in bug report template
Adds a required "Link to reproduction" input field asking users to push
a minimal repro to a public GitHub repo (scaffolded via
`hyperframes init repro --non-interactive --example blank`).
Also consolidates the OS/Node/FFmpeg/version fields into a single
"Environment" field using `npx hyperframes info` output — fewer fields
to fill, more consistent data.
Follows the same pattern as Next.js and Gatsby issue templates.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(issue-template): use hyperframes doctor for environment info
`hyperframes info` only prints project metadata (resolution, duration,
elements). `hyperframes doctor` prints the full environment: version,
Node.js, FFmpeg, Chrome, memory, disk, Docker — everything needed to
diagnose bugs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs(prompting): mention validate alongside lint in anti-patterns
Per Vance's review comment — validate catches runtime errors (JS
exceptions, missing assets, contrast) that lint doesn't.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: replace libretto example URL with hyperframes repo
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## 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)
Add a FIFO semaphore to limit concurrent renders in the producer server,
preventing Chrome CPU contention that causes beginFrame failures.
- New Semaphore utility class (packages/producer/src/utils/semaphore.ts)
- Both blocking render and SSE renderStream handlers acquire/release the semaphore
- SSE stream sends a "queued" event when request must wait
- New GET /render/queue endpoint exposes active/queued render counts
- Configurable via HandlerOptions.maxConcurrentRenders or PRODUCER_MAX_CONCURRENT_RENDERS env var (default: 2)
- New --max-concurrent-renders CLI flag (1-10)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## Summary
- Adds `--format mov` to the render CLI for ProRes 4444 transparent video output
- ProRes 4444 with alpha is the industry standard for transparent video overlays, supported by CapCut, Final Cut, Premiere, DaVinci, and After Effects
- WebM VP9 alpha technically works but is ignored by all major video editors — only browsers decode it
- Adds MOV to the studio export dropdown alongside MP4 and WebM
## Transparency format comparison
| Format | Codec | Alpha | Video editors | Browsers | File size |
| --- | --- | --- | --- | --- | --- |
| **MOV** | ProRes 4444 | Yes | CapCut, Final Cut, Premiere, DaVinci, After Effects | No (won't play in browser) | Large (~5-40 MB) |
| **WebM** | VP9 | Yes | None (shows black) | Chrome, Firefox | Small (~200 KB) |
| **MP4** | H.264 | No | All | All | Small |
> **Note:** ProRes MOV files do not play in Chromium browsers — they are an intermediate/editing format, not a delivery format. Use [rotato.app/tools/transparent-video](https://rotato.app/tools/transparent-video) to verify transparency works correctly.
## Changes
- **CLI**: Add `mov` to `--format` validation, examples, and output path logic
- **Engine**: `getEncoderPreset()` returns ProRes 4444 (`yuva444p10le`) for `mov` format; handle `.mov` in `applyFaststart` and `muxVideoWithAudio`; add `pix_fmt` to streaming encoder ProRes path
- **Producer**: Treat `mov` like `webm` for alpha capture (PNG frames, screenshot mode, `forceScreenshot`)
- **Studio**: Add MOV option to export format dropdown and render queue hook
- **Core**: Add `mov` to studio API types, render route, and mime helpers
- **Tests**: Add encoder preset tests for mov format (42 total, all passing)
## Usage
```bash
hyperframes render --format mov --output overlay.mov
```
## Test plan
- [x] `pnpm build` passes
- [x] `pnpm --filter @hyperframes/engine test` — 42 tests pass (2 new for MOV)
- [x] `oxlint` and `oxfmt` clean on all 12 changed files
- [x] End-to-end local render produces ProRes 4444 (`yuva444p12le`) with working alpha
- [x] Docker render with `--format mov` — ProRes 4444 confirmed via ffprobe
- [x] Studio dropdown shows MOV option in built JS
- [x] Transparency verified with [rotato.app/tools/transparent-video](https://rotato.app/tools/transparent-video)
* feat(docs): add template gallery page with visual previews
* fix(docs): remove invalid MDX heading anchors
* chore: retrigger CI
* feat(docs): merge gallery into templates page with hover-to-play video previews
- Consolidated gallery.mdx and templates.mdx into single templates.mdx
- Moved templates page to Getting Started section
- Added MP4 video previews rendered by hyperframes (hover to play)
- Custom JS for hover-to-play behavior (Mintlify strips JSX event handlers)
- 2-column grid for landscape, 3-column for portrait
- Remotion-style cards with gradient overlay labels
* fix(docs): update broken links after templates page move
* ci(regression): remove scripts/ from regression trigger paths
scripts/ contains dev utilities (lint, versioning, preview generation)
that don't affect the rendering engine.
* feat(skills): add hyperframes-cli skill for CLI workflow guidance
Adds a new skill that teaches AI agents how to use the HyperFrames CLI
(init, lint, dev, render, doctor). Previously, agents had no way to
discover the CLI — the compose-video skill only covered HTML authoring.
This led to agents searching for binaries, finding the monorepo, and
running bun run studio manually instead of using npx hyperframes dev.
Also registers the skill in init.ts so new projects get it bundled
alongside hyperframes-compose and hyperframes-captions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor(cli): rename dev command to preview
The command starts a preview server — "preview" describes what users
are doing more accurately than "dev". Updates the command name, file
name, all CLI references, docs, skills, and template CLAUDE.md.
22 files updated across CLI source, docs, skills, and templates.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(skills): replace stale dev reference with preview in CLI skill
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(docs): catch remaining dev references missed in rename
- testing-local-changes.mdx: two inline command examples
- troubleshooting.mdx: anchor link #dev → #preview, "dev server" → "preview server"
- cli.mdx: "dev server" → "preview server"
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace the hardcoded default of 4 workers with a CPU-aware heuristic:
half of available CPU cores, capped at 4. Each worker spawns a separate
Chrome browser process (~256MB RAM each), so the previous default of 4
caused resource contention on smaller machines.
The new defaults:
2-core laptop → 1 worker
4-core laptop → 2 workers
8-core desktop → 4 workers
16-core server → 4 workers (capped)
Also adds --workers auto flag support, improves help text to explain
what workers do, and adds a Workers section to the rendering docs with
guidance on when to increase or decrease parallelism.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Major improvements across all 18 pages:
- Use Mintlify components: <Steps> for tutorials, <Tabs> for alternatives,
<CodeGroup> for multi-platform commands, <Tree> for directory structures,
<AccordionGroup> for FAQ/scannable content, <Mermaid> for diagrams
- Add filename annotations to all code blocks (e.g., ```html index.html)
- Add numbered comments inside multi-step code examples
- Show expected terminal output after CLI commands
- Add "When to use" / "When NOT to use" sections to all package pages
- Add "Next Steps" CardGroup to every page (no dead-end pages)
- Cross-link between pages at point of curiosity (not just "see also" dumps)
- Expand thin pages (engine, studio) with architecture details and examples
- Add decision guides (rendering modes, template selection)
- Use <Warning> and <Note> sparingly (max 2-3 per page)
Also adds DOCS_GUIDELINES.md at repo root with writing standards.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>