mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-01 19:42:03 +00:00
sync/hyperframes-codegen-3ff80b22
135
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
8228932e17 |
fix(scripts): make release change-guard robust to git status prefix (#1198)
The set-version guard parsed `git status --porcelain` and extracted the path with a fixed `line.slice(3)`. The porcelain "XY <path>" prefix width can shift, and when it did the slice dropped a leading character — misreading `.claude-plugin/plugin.json` as `claude-plugin/plugin.json`, which failed the allowed-paths match and falsely blocked a legitimate release with "Unexpected uncommitted changes". There was no escape hatch. Collect changed paths from `git diff --name-only -z HEAD` (tracked) plus `git ls-files --others --exclude-standard -z` (untracked) instead. Both emit bare NUL-separated repo-relative paths with no status column to misparse, so the allowed-paths comparison is exact. Extract the pure helpers (splitNulList, findUnexpectedChanges) and cover them with tests. Also document the release flow in CLAUDE.md (the repo had no release docs). |
||
|
|
1abe69f3e4 | feat(docs): add weekly update drafts (#1183) | ||
|
|
17b0db1d3e |
chore: add release prepare command (#1165)
## What - Add `bun run release:prepare <version>` as the maintainer-facing stable release entrypoint. - Make the first run draft missing changelog artifacts and intentionally exit before tagging; rerunning after manual review delegates to `set-version`. - Tighten the direct `set-version` guard so stable releases also fail when generated TODO changelog copy is still present. - Update maintainer docs to recommend `release:prepare` while keeping `changelog:draft` as the lower-level regeneration tool. ## Why Stable releases should be hard to run without reviewed GitHub release notes and Mintlify changelog copy. This keeps the existing manual rewrite step, but makes the expected path one command that engineers can rerun after review. ## How - Added `scripts/release-prepare.ts` with parsing, draft/review/set-version action selection, and command forwarding. - Added focused script tests for parser behavior, action selection, command forwarding, and TODO detection. - Extracted shared script CLI parsing helpers so `changelog:draft` and `release:prepare` use the same option handling. - Adjusted `changelog:draft --write` so an existing release file is left unchanged unless `--force` is passed, while still allowing a missing docs entry to be added. ## Test plan - [x] Unit tests added/updated: `bun run test:scripts` - [x] Format check: `bun run format:check` - [x] Lint: `bun run lint` - [x] Typecheck: `bun run --filter '*' typecheck` - [x] Fallow audit: `bunx fallow audit --base origin/main --fail-on-issues` - [x] Manual CLI checks: `bun run release:prepare --help`; `bun run set-version 9.9.9` fails before mutation when changelog artifacts are missing - [x] Documentation updated |
||
|
|
248f640734 |
feat(docs): add changelog release workflow (#1164)
* feat(docs): add changelog release workflow * fix(scripts): resolve CodeQL findings in release scripts - draft-changelog.ts: replace existsSync+writeFileSync check-then-act with an atomic exclusive-write flag (flag: wx) to fix the js/file-system-race TOCTOU finding; overwrite only under --force (flag: w). - set-version.ts: switch execSync shell-string git calls to execFileSync with argument arrays so the interpolated version/paths can never be interpreted by a shell, resolving the js/indirect-command-line-injection findings. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(scripts): lower writeReleaseNotes complexity below CRAP threshold The exclusive-write fix pushed writeReleaseNotes to cyclomatic 5 / CRAP 30.0 (fallow/high-crap-score, threshold 30.0). The '!force' guard in the catch is redundant — EEXIST is only reachable under the 'wx' flag (force=false), since 'w' overwrites without throwing. Dropping it returns the function to cyclomatic 4 / CRAP 20 with identical behavior. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(docs): address changelog review feedback --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
1ee920b535 |
fix(release): bump plugin manifests in set-version
scripts/set-version.ts only bumped the npm package.json files, so the Claude Code / Codex / Cursor plugin manifests stayed at 0.1.0 across every release. Claude Code gates /plugin update on plugin.json's version, so users never received accumulated changes (closes #1048). Add a PLUGINS list and a parallel loop that rewrites each manifest's version, and include the manifests in the clean-tree guard and the staged file set. The loop replaces only the version string (not a JSON round-trip) to preserve each file's exact formatting, since oxfmt keeps their short arrays inline and JSON.stringify would expand them and fail the pre-commit format check. |
||
|
|
ffbc18ad31 |
feat(studio): full Blocks panel — browse, search, add, drag-and-drop registry items
Adds a Blocks tab to the Studio left sidebar with the full 78-item registry
catalog (58 blocks + 20 components). Users can browse by category, search by
title/description, preview CDN-hosted poster thumbnails with video-on-hover,
and install items on-demand with one click or drag-to-timeline.
Core changes:
- BlockCategory type + resolveBlockCategory() for 7 categories (Captions, VFX,
Transitions, Effects, Social, Data, Scenes)
- Registry API routes: GET /api/registry/blocks (catalog) + POST install
- StudioApiAdapter extended with listRegistryCatalog + installRegistryBlock
- Vite adapter reads from disk; CLI adapter fetches from GitHub (24h cache)
- BlockParam interface + params on 6 blocks for future parameter controls
Studio UI:
- 4th sidebar tab "Blocks" with responsive grid, category pills, search bar
- BlockCard: CDN poster thumbnail, video autoplay on hover, duration + WebGL badges
- On-demand install: blocks append as sub-compositions on timeline; components
overlay at start=0 spanning full duration with transparent background patching
- TIMELINE_BLOCK_MIME drag-and-drop to timeline
- BlockParamsPanel (Phase 3 scaffold) auto-opens for parameterized blocks
Registry manifests:
- All 58 blocks backfilled with preview: { video, poster } CDN URLs
- All 20 components normalized to object format + poster URLs added
- 6 blocks annotated with params (Liquid Glass/Background, Portal, Chart,
Logo Outro, Magnetic)
- flowchart-vertical preview generated and uploaded to CDN
|
||
|
|
4f274d3605 |
Merge pull request #920 from heygen-com/chore/aws-lambda-publish-ready
chore(lambda): publish-readiness for @hyperframes/aws-lambda |
||
|
|
6935eaabc4 |
chore(lambda): bump initial version to 0.6.20 + add to set-version
Two follow-ups to keep the new package in lockstep with the rest of the @hyperframes/* release cadence from day one: - Bump packages/aws-lambda/package.json version 0.6.18 → 0.6.20 so it matches what main released while this PR was in review. Without this, the package would land below the rest of the lockstep and the next release-bump would jump aws-lambda from 0.6.18 → 0.6.21 in one step. - Add packages/aws-lambda to PACKAGES in scripts/set-version.ts so the next `chore: release vX.Y.Z` commit bumps aws-lambda alongside the other publishable packages. Without this, set-version silently skips aws-lambda — package.json stays frozen, pnpm publish would re-publish the same version on every release, and the npm-view precheck in publish.yml would skip-with-success and never actually push a new version of the package. |
||
|
|
ae193d99b9 |
fix(registry): align timeline IDs and regenerate catalog index
- Fix timeline_id_mismatch on all 15 caption components: __timelines key now matches data-composition-id (e.g. "caption-clip-wipe" not "clip-wipe") - Regenerate docs/public/catalog-index.json with 15 new caption entries - Add "Captions" group mapping to generate-catalog-pages.ts (priority 0) - Regenerate docs.json nav and mdx pages via the catalog script - Upload docs preview videos to docs/images CDN path |
||
|
|
f84cc492de |
perf(engine): faster shader transitions via page-side WebGL compositing (#832)
* fix(cli): prefer puppeteer cache + numeric version sort (staff review) Two correctness fixes from PR #821 self-review: 1. Cache priority order. Previous order was hyperframes-managed cache → puppeteer cache. HF cache is pinned to CHROME_VERSION (131-era) which lags 17+ releases behind upstream; if a user separately installed a newer chrome-headless-shell via @puppeteer/browsers install, the CLI would silently hand engine the older HF-cache binary while engine's own resolveHeadlessShellPath would have picked the newer one. Flip the priority so puppeteer cache wins, matching engine semantics. 2. Numeric (not lexicographic) version sort. `readdirSync.sort().reverse()` over names like `linux-148.0.7778.97` and `linux-99.0.6533.123` would return `linux-99...` first because character '9' outranks '1'. Parse each name into integer segments and compare them numerically. Tests: add both-caches-populated and linux-148-beats-linux-99 cases. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * perf(engine): page-side compositing for shader transitions (opt-in spike) Add an opt-in `--page-side-compositing` flag (CLI) backed by a new engine config field `enablePageSideCompositing` and env var `HF_PAGE_SIDE_COMPOSITING`. When set, SDR shader-transition compositions skip the Node-side layered blend (the hf#677 chain) and instead run the shader inside Chrome via a page-side WebGL canvas; the engine then captures ONE opaque RGB frame per output frame via the existing streaming capture path. This is the strongest non-beginFrame perf lever for Mac users, who cannot take the beginFrame `~5×` path (Chromium structural limit, crbug.com/40656275). Stacks on top of the hf#677 1.95× baseline. Default OFF — existing fixture pins (byte-exact MP4 output) are preserved. Opt-in path is intentionally PSNR-pinned, not byte-equal (WebGL is f32; Node is f64). HDR content forces the existing layered path regardless. Implementation: - engine: new `EngineConfig.enablePageSideCompositing` (default false). - producer/fileServer: new `HF_PAGE_SIDE_COMPOSITING_STUB` early-page script injected into the served HTML head when the flag is on. - producer/renderOrchestrator: when the flag + no HDR + no png-sequence, route SDR transitions through the streaming path instead of the layered HDR stage. - shader-transitions: new `engineModePageComposite.ts` installs a fullscreen WebGL compositor overlay and wraps `window.__hf.seek` so each seek inside a transition window captures both scenes via the Chromium `drawElementImage` API to GL textures, runs the fragment shader, and displays the composited result on the overlay canvas. The engine takes one screenshot per frame and sees the composited overlay. - cli: new `--page-side-compositing` flag sets `HF_PAGE_SIDE_COMPOSITING=true` before producer load. - scripts/page-side-compositing-smoke: bundled-CLI smoke that renders a representative fixture with and without the flag, validates the canary strings are in the shipped bundles, and writes a wall-time pair. Determinism trade documented in the engine config doc-comment. The smoke script enforces the bundled-CLI validation discipline from prior perf work (see internal feedback note `validate_bundled_cli_not_dev_path`). Runtime requirement: Chromium's `CanvasDrawElement` feature (already enabled by the engine's `--enable-features=CanvasDrawElement` launch flag). When the runtime feature is unavailable, the page-side installer logs a warning and falls back to opacity-flip mode — the engine still takes the streaming path; the transition window degrades to a hard scene swap. Vance will validate on Mac Chrome where the feature is supported. Co-Authored-By: Vai <vai@heygen.com> * fix(shader-transitions): use html2canvas for page-side compositor capture The original drawElementImage approach fails in engine render mode because the virtual-time shim prevents Chromium from generating paint records for cloned elements. drawElementImage requires a cached paint record from the browser's compositor — clones created at capture time never receive one because (a) shimmed rAFs deadlock inside the seek wrapper, (b) original rAFs don't produce real paints under virtual-time control, and (c) layoutsubtree canvases don't apply CSS stylesheet rules to children. Switch scene capture to html2canvas (foreignObjectRendering: false), the same JS-based renderer already used by the preview-mode fallback path in capture.ts. html2canvas reads computed styles and renders via its own canvas drawing pipeline with no dependency on the browser paint cycle. Also fixes: - Engine seek must return the result so Puppeteer awaits async seek promises (frameCapture.ts). - GSAP opacity cache: compositor must restore scene opacity before seek, not after — GSAP caches inline values and skips re-writes. - Support check gates on WebGL availability, not drawElementImage. Perf: 15-scene shader-perf fixture (28s, 14 transitions, 30fps) Baseline (Node-side layered): 137s Page-side (html2canvas+WebGL): 33s → 4.1× speedup Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(shader-transitions): simplify review fixes for page-side compositor - Use uploadTexture (zeroes canvas backing store after upload) to prevent ~2.2GB transient memory pressure across 280 html2canvas calls per render - Add ignoreElements + stabilizeTransformedBoxShadows to html2canvas call, matching the preview-path capture.ts behavior - Parallelize from/to scene captures with Promise.all - Wrap post-capture render in try/finally so opacity is always restored - Fix WebGL context leak in isPageSideCompositingSupported probe - Remove dead ResolvedTransition.index field - Export stabilizeTransformedBoxShadows from capture.ts Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(producer): unify page-side compositing gating and Docker forwarding Addresses three issues from staff review: 1. ignoreElements filter stripped all in-scene canvases (Chart.js, D3, p5.js) — narrowed to data-no-capture only since the compositor canvas is a body sibling never in the scene subtree. 2. Docker mode silently dropped --page-side-compositing — thread pageSideCompositing through DockerRenderOptions/buildDockerRunArgs with regression tests. 3. Fragmented gating across 4 independent sites could disagree: - Stub injection gated only on cfg flag (leaked into HDR/alpha) - Probe-created fileServer never got the stub - needsAlpha (WebM/MOV) not excluded from the gate - WebGL-unavailable fallback claimed layered path would run but orchestrator had already disabled it Fix: compute stub injection at the same site as the layered-bypass decision (after hasHdrContent is known), using addPreHeadScript on the already-running fileServer. Single predicate now gates both decisions, including !needsAlpha. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * perf(engine): two-phase drawElementImage capture for page-side compositing Replace html2canvas with native drawElementImage for scene capture in the page-side compositor. drawElementImage reads from the browser's own paint cache, giving pixel-identical output to the preview path. The blocker was that cloned elements inside layoutsubtree canvases have no cached paint record under virtual time — the compositor only paints when explicitly triggered. Fix: split the seek+composite into two phases with an engine-forced paint between them. Phase 1 (seek wrapper, page-side): - GSAP seek positions the timeline - Clone FROM/TO scenes into visible layoutsubtree staging canvases - Set window.__hf_page_composite_pending flag Engine paint force (frameCapture.ts): - Detect pending flag after seek returns - Fire micro Page.captureScreenshot (1x1 clip) via CDP to force the browser compositor to paint all visible elements including staging canvas children Phase 2 (page.evaluate, page-side): - drawElementImage reads the now-valid paint records - Upload textures to WebGL, run shader, show GL overlay Key insight: staging canvases must be visible (not opacity:0) for the browser to paint their children. They sit at z-index:-9998, behind the main DOM and covered by the GL overlay during transitions. Perf: 15-scene fixture (28s, 14 transitions, 30fps): Baseline (Node-side layered): 137s html2canvas + WebGL: 33s (3.7×) drawElementImage + WebGL: 21s (6.6×) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * perf(engine): optimize two-phase compositor hot path - uploadTextureSource instead of uploadTexture: eliminates ~2.3GB of canvas buffer alloc/dealloc churn (persistent staging canvases don't need the one-shot zeroing behavior) - Fold hasPending check into seek page.evaluate: eliminates one CDP round-trip per frame (~700 unnecessary IPC calls on non-transition frames) - Fix renderShader error handling: on failure, leave source scenes visible as fallback instead of hiding both scenes + GL overlay (which produced black frames) - Move mutable state declarations above resolveComposite to prevent TDZ risk on refactor Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(engine): staff review — staging cleanup, pending flag, beginFrame guard - Clear staging canvas children when leaving transition window (prevents visible clone bleed-through on transparent compositions) - Clear __hf_page_composite_pending on all resolveComposite exit paths - Guard micro-screenshot paint force against beginFrame mode (CDP Page.captureScreenshot conflicts with beginFrame compositor control) - Update CLI flag description: document video/canvas limitation, remove stale PSNR claim Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(engine): default-on page-side compositing for SDR shader transitions Page-side compositing is now enabled by default for SDR shader-transition renders without video content. The 6.6× speedup applies automatically — no flag needed. Auto-disables when: - HDR content detected - Alpha output (WebM/MOV/PNG-sequence) - Composition contains <video> elements (cloneNode loses playback state) - beginFrame capture mode (Linux headless) Use --no-page-side-compositing to force the Node-side layered path. Changes: - Engine config: enablePageSideCompositing defaults to true - CLI: flag default flipped to true; --no-page-side-compositing disables - Orchestrator: added composition.videos.length === 0 gate - Docker: forwards --no-page-side-compositing when explicitly disabled - Config tests updated for new default Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(engine): support video elements on page-side compositing fast path Three-phase capture protocol lets shader transitions render video scenes without falling back to the slow Node-side layered pipeline: 1. Seek → compositor records transition metadata, sets pending flag 2. onBeforeCapture → video frame injector updates <img> replacements 3. prepare → cloneNode picks up current video frames, img.decode() awaits 4. micro-screenshot → forces browser to paint cloned elements 5. resolve → drawElementImage reads paint records, shader composites Key changes: - Remove `composition.videos.length === 0` gate from orchestrator - Split compositor resolve into prepare (clone) + resolve (shader) - Move onBeforeCapture before compositor prepare in frameCapture.ts - Await img.decode() on cloned data-URI images to prevent stale frames - Stop manipulating scene opacity in compositor (GL canvas overlay suffices) - Add gsap.set declaration for shader-transitions ambient types - Add video_missing_timing_attrs lint rule for <video> without id/data-start/data-end Performance: compositions with video now render at 7.5s (6 workers) instead of 2m38s on the layered path. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(core): auto-inject data-start on video/audio so frame extraction works without explicit attrs The timing compiler now injects data-start="0" on <video> and <audio> elements that lack it. This makes discoverMediaFromBrowser() find the element (it queries video[data-start]), so the frame extraction pipeline activates automatically. Videos "just work" without requiring authors to add data-start, data-end, or id attributes. Also removes the video_missing_timing_attrs lint rule — the compiler handles the missing attributes automatically, so the lint rule would only false-positive. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(core): add data-hf-auto-start sentinel on auto-injected video timing Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(producer): add discoverVideoVisibilityFromTimeline for runtime video discovery Seeks the GSAP timeline in Puppeteer to discover when each video's parent scene is visible (opacity > 0). Uses coarse sampling at 100ms steps followed by binary search refinement to frame-level precision (1/60s). Only processes videos with the data-hf-auto-start sentinel so author-specified timing is never overridden. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(producer): integrate runtime video visibility discovery into probe stage Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(producer): trigger browser probe for auto-start videos, remove debug logging The probe stage was skipping browser launch when composition duration was already known, which meant discoverVideoVisibilityFromTimeline never ran. Now needsBrowser also checks for data-hf-auto-start sentinel in compiled HTML. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(scripts): use mkdtempSync for smoke test work directory Replaces hardcoded /tmp/hf-page-side-smoke with a unique temp directory via mkdtempSync to resolve CodeQL "insecure temporary file" alert. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * style: format smoke test script Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: Vai <vai@heygen.com> |
||
|
|
91f811d4d5 |
fix(scripts): pass rational fps to capture/render in catalog previews
`scripts/generate-catalog-previews.ts` still called `createCaptureSession`
with `fps: 30` and `createRenderJob` with `fps: 24`. Since commit
|
||
|
|
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 |
||
|
|
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. |
||
|
|
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. |
||
|
|
ef45f653ff | ci: guard release channel publishing (#488) | ||
|
|
9ef864d1f2 |
fix(docs): serve hyperframes.json / registry JSON schemas (#304) (#305)
Closes #304. ## Summary The three `/schema/*.json` URLs baked into every Hyperframes project as `\$schema` references are 404ing on the live docs site — blocking editor autocomplete and validation. - \`https://hyperframes.heygen.com/schema/hyperframes.json\` — **404** (missing entirely) - \`https://hyperframes.heygen.com/schema/registry.json\` — **404** (only in npm package) - \`https://hyperframes.heygen.com/schema/registry-item.json\` — **404** (only in npm package) Mintlify serves top-level non-MDX dirs in \`docs/\` at \`/\<dir>/*\` (confirmed by \`docs/logo/*.svg\` → \`/logo/*.svg\`). This PR drops the three schemas into \`docs/schema/\` so the URLs resolve. ## What changed | File | Role | |---|---| | \`docs/schema/hyperframes.json\` | **New.** Authored from the \`ProjectConfig\` type in \`packages/cli/src/utils/projectConfig.ts\`. | | \`docs/schema/registry.json\` | Mirror of \`packages/core/schemas/registry.json\`. | | \`docs/schema/registry-item.json\` | Mirror of \`packages/core/schemas/registry-item.json\`. | | \`scripts/sync-schemas.ts\` | Keeps the registry mirrors in lockstep with their authoritative copies in \`packages/core/schemas/\`. \`--check\` mode fails the Docs workflow on drift. | | \`.github/workflows/docs.yml\` | Runs \`tsx scripts/sync-schemas.ts --check\` on every PR touching docs or core schemas. | | \`package.json\` | \`sync-schemas\` / \`sync-schemas:check\` npm scripts. | ## Why not make \`packages/core/schemas/\` authoritative for \`hyperframes.json\` too? \`hyperframes.json\` is CLI config, not a core type. Keeping the schema in \`docs/\` avoids an artificial dependency between \`@hyperframes/core\` and \`@hyperframes/cli\`. If the two ever need to align, we can flip the direction then. ## Verification - \`bun run sync-schemas:check\` → \`2/2 in sync\`. - Ajv (draft 2020-12, in-process) validation against 9 cases: - ✓ real factory-series-c-video config - ✓ default shape from \`hyperframes init\` - ✓ \`\$schema\` is optional - ✓ missing registry → rejected - ✓ missing paths.assets → rejected - ✓ extra top-level key → rejected - ✓ empty registry string → rejected - ✓ empty block path → rejected - ✓ missing paths entirely → rejected ## Test plan - [x] \`tsx scripts/sync-schemas.ts --check\` passes locally - [x] Schemas parse as valid JSON and validate real/default project configs - [x] After merge: \`curl -sI https://hyperframes.heygen.com/schema/hyperframes.json\` returns 200 once Mintlify redeploys - [x] Same check for \`/schema/registry.json\` and \`/schema/registry-item.json\` - [x] VS Code autocomplete and error-highlighting work on \`hyperframes.json\` without extra config ## Notes - The Docs workflow now triggers on \`packages/core/schemas/**\` and \`scripts/sync-schemas.ts\` in addition to \`docs/**\`, so a core-schemas change that forgets to run \`sync-schemas\` will fail CI instead of silently publishing stale docs. - No runtime / API changes to any package; ship independent of a version bump. |
||
|
|
4ae5c0340f |
chore(docs): migrate docs/images/ media to static.heygen.ai CDN (#301)
Move all preview mp4/png/gif assets under docs/images/ out of the repo and serve them from https://static.heygen.ai/hyperframes-oss/docs/images/ (backed by s3://heygen-public/hyperframes-oss/docs/images/, CloudFront). Drops ~49MB from the working tree and, more importantly, ~49MB from every future Mintlify build checkout. Combined with the (already-LFS-tracked) producer snapshots, the remaining bloat in 'npx skills add heygen-com/ hyperframes' (see #300) is LFS smudge during clone — separate fix needed in the skills CLI to pass GIT_LFS_SKIP_SMUDGE=1. Changes: - Delete docs/images/** (103 files, ~49MB). Files are uploaded to S3 already. - Rewrite /images/* references in 44 MDX files, TemplateCard.jsx, and catalog-index.json to absolute CDN URLs. - Update README.md img src to CDN URL (renders correctly on GitHub). - Add docs/images/ to .gitignore so regenerated previews aren't committed. - Add scripts/upload-docs-images.sh to sync docs/images/ → S3 after running the preview generators. - Wire up bun run upload:docs-images and bun run generate:catalog-previews scripts in package.json. - Update generator script docstrings to point at the upload step. External contributors can still regenerate previews locally (mintlify dev reads the CDN URLs, so broken previews appear only for newly added items pending a maintainer upload). Maintainers run: bun run generate:catalog-previews --only <name> bun run upload:docs-images Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> |
||
|
|
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 |
||
|
|
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
|
||
|
|
b32611c2c3 |
docs: codegen per-item MDX pages from registry (#263)
## What
Script that auto-generates per-item catalog documentation from `registry-item.json` manifests.
**New file:** `scripts/generate-catalog-pages.ts`
**Outputs:**
- `docs/catalog/blocks/<name>.mdx` — per-block detail page
- `docs/catalog/components/<name>.mdx` — per-component detail page
- `docs/public/catalog-index.json` — flat manifest for the grid page (constant-sized regardless of catalog size)
- Updates `docs/docs.json` with a Catalog tab containing Blocks + Components groups
## Why
Phase B of the catalog plan (PR 9). After this lands, future content PRs don't need to write MDX by hand — the script generates everything from `registry-item.json`.
## How
The script:
1. Walks `registry/blocks/*/registry-item.json` and `registry/components/*/registry-item.json`
2. **Wipes `docs/catalog/` before regenerating** — deleted items don't leave stale pages
3. Generates MDX per item with: title, description, tag badges, preview image, install command, details table, files table, usage hint, and related skill link
4. Emits `catalog-index.json` with `{name, type, title, description, tags, href, preview}` per item
5. Updates `docs.json` navigation — inserts or replaces the Catalog tab with current block/component page lists
Run before Mintlify builds: `npx tsx scripts/generate-catalog-pages.ts`
## Test plan
- [x] Script compiles — passes `lefthook` typecheck + lint + format
- [x] CONTRIBUTING.md documents the auto-generation workflow
- [ ] Full end-to-end test requires PRs 6+7 to merge first (items must exist in registry/)
|
||
|
|
ea6f949922 |
ci: render catalog previews on PR (#262)
## What
CI workflow that auto-renders preview thumbnails for new/changed registry blocks and components on pull requests.
**New files:**
- `scripts/generate-catalog-previews.ts` — catalog preview renderer supporting all three registry item types
- `.github/workflows/catalog-previews.yml` — GitHub Actions workflow triggered on PRs touching `registry/blocks/` or `registry/components/`
## Why
Phase B of the catalog plan (PR 8). After this lands, future block/component PRs don't need to manually generate preview images — CI handles it automatically.
## How
The preview script discovers items from the registry directory structure:
- **Examples**: renders `index.html` (same as the existing `generate-template-previews.ts`)
- **Blocks**: renders the block's standalone HTML file directly (e.g., `data-chart.html`)
- **Components**: renders the component's `demo.html` (the demo.html convention from PR 7)
The CI workflow:
1. Detects which blocks/components changed in the PR via `git diff`
2. Renders thumbnails for only the changed items (not the full catalog)
3. Uploads preview PNGs as artifacts
Output goes to `docs/images/catalog/<type>/<name>.{png,mp4}` (separate from the existing `docs/images/templates/` directory).
Supports CLI flags: `--only <name>`, `--type <example|block|component>`, `--skip-video`.
## Test plan
- [x] Script compiles and passes typecheck (`lefthook pre-commit` ran lint + typecheck + format)
- [x] Workflow YAML is valid (standard GitHub Actions syntax, follows existing ci.yml patterns)
- [ ] Full end-to-end test requires Chrome + FFmpeg (runs in CI, not testable locally without producer deps)
|
||
|
|
9bf4956fae |
chore(shader-transitions): add to CI publish pipeline and README (#264)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
08fb1de61f |
feat(cli): add command + hyperframes.json (#256)
## 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) |
||
|
|
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) |
||
|
|
e6a38c9e0f | feat(ci): add alpha/beta/rc pre-release support to publish workflow (#167) | ||
|
|
6b1463fd5b |
refactor(cli): move templates to templates/ for remote fetching (#161)
* refactor(cli): move templates to examples/ for remote fetching * refactor(cli): rename examples/ to templates/ for clarity Follows Remix/Vite convention — these are init scaffolds, not general examples. |
||
|
|
fee51f7a65 |
feat(docs): add template gallery page with visual previews (#160)
* 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. |
||
|
|
05aceedd30 |
feat(docs): add template preview generation script (#159)
## What Add a script that uses `@hyperframes/producer` to render PNG thumbnails of each built-in template. Output goes to `docs/images/templates/`. ## Why User feedback: "I would have loved more visual examples of what's actually possible. I had to scaffold every template just to see what they look like." This is the foundation for a visual template gallery in the docs. ## How - New `scripts/generate-template-previews.ts` uses the producer's `createFileServer` + `createCaptureSession` + `captureFrame` APIs — hyperframes renders its own templates - Patches out `__VIDEO_SRC__` placeholders (same logic as `init.ts`) so templates render without a video file - Captures a frame at t=2s for each template (skips `blank` — it's just empty scaffolding) - Handles varying dimensions (vignelli is 1080x1920 portrait) - Adds `pnpm generate:previews` npm script ## Test plan - [x] `pnpm generate:previews` generates 8 PNGs in `docs/images/templates/` - [x] Each PNG is visually correct (verified by viewing) - [x] `--only <template>` flag works for single template generation |
||
|
|
a9d49cd528 |
fix(cli): auto-copy all templates to dist and add skill lint (#153)
- Replace hardcoded template list in build:copy with `cp -r src/templates/*` so new templates are included automatically (kinetic-type, decision-tree, product-promo, nyt-graph were missing from published package) - Fix captions SKILL.md: reword `!` and `>` in inline backticks that triggered Claude Code's bash permission checker - Add scripts/lint-skills.ts to catch shell-unsafe patterns in SKILL.md files (runs as part of `bun run lint` in CI) Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
24c4fa6041 |
fix: make set-version commit and tag by default (#143)
The --tag flag was optional, which led to v0.1.11 and v0.1.12 being bumped without tags — skipping npm publish entirely. Invert the default: always commit + tag, with --no-tag as the escape hatch. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
e1c1c6fb30 |
fix: rewrite workspace deps before npm publish (#67)
## Summary - rewrite workspace protocol dependencies to publish-safe semver ranges before the npm publish workflow runs - keep workspace protocol references in source manifests for normal monorepo development - ensure the published `@hyperframes/producer` manifest no longer ships unresolved `workspace:` deps ## Why The internal repo hit a Docker build failure because the published `@hyperframes/producer` metadata still contained `workspace:^` dependencies for `@hyperframes/core` and `@hyperframes/engine`. `npm install` cannot resolve those outside the monorepo, so the published package itself was the root cause. ## Validation - `bun install --frozen-lockfile` - `bun run build:producer` - `bun run prepare:publish-manifests` - `npm pack --workspace packages/core` - `npm pack --workspace packages/engine` - `npm pack --workspace packages/producer` - installed the three tarballs together in a clean temp project with `npm install --ignore-scripts` - extracted the producer tarball and verified its `package.json` contains `^0.1.3` for `@hyperframes/core` and `@hyperframes/engine`, not `workspace:^` |
||
|
|
61c5257402 |
fix(ci): update publish workflow to use bun install (#36)
* fix(ci): update publish workflow to use bun install pnpm-lock.yaml was removed in the bun migration but publish.yml still referenced it. Use bun for install/build, keep pnpm for publish (publishConfig overrides + --provenance). * docs: update stale pnpm references to bun across docs and scripts Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> |
||
|
|
20be2ea1c2 |
style: apply oxfmt baseline formatting across all source files (#25)
## Summary - Run `oxfmt .` across the entire codebase to establish formatted baseline - 299 files changed — mechanical formatting only, no logic changes - Double quotes, semicolons, 2-space indent, trailing commas, 100 print width Part 3/4 of [VA-851](https://linear.app/heygen/issue/VA-851/pre-migration-configure-eslint-prettier-and-conventional-commits) ## Test plan - [x] `pnpm format:check` — all 426 files pass - [x] `pnpm -r typecheck` — all packages pass - [x] `pnpm build` — all packages build - [x] All 348 tests pass |
||
|
|
306909534b | ci: add tag-triggered npm publish workflow with OIDC provenance |