Commit Graph
177 Commits
Author SHA1 Message Date
James Russo 1abe69f3e4 feat(docs): add weekly update drafts (#1183) 2026-06-03 17:27:27 -07:00
Miguel Ángel f5d81cb5a7 chore: release v0.6.70 2026-06-03 04:41:52 +00:00
James Russo 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
2026-06-02 20:34:29 -04:00
James RussoandClaude Opus 4.8 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>
2026-06-02 15:51:16 -07:00
Miguel ÁngelandClaude Sonnet 4.6 689deaf4b8 feat(registry): add Apple Terminal theme code snippet blocks (#1161)
* feat(registry): add Apple Terminal theme code snippet blocks

Adds 12 Apple Terminal built-in profile visualizer blocks to the
Code Snippets catalog section, following the same pattern as the
VS Code theme blocks (commit 5245e190).

Themes: Basic, Clear Dark, Clear Light, Grass, Homebrew, Man Page,
Novel, Ocean, Pro, Red Sands, Silver Aerogel, Solid Colors.

Each block is a self-contained 1920×1080 composition showing a
macOS Terminal.app window in the matching profile colors, with
per-character GSAP typing animation and window.__timelines contract.

Install individually:
  npx hyperframes add code-snippet-apple-terminal-basic

Install all Apple Terminal themes:
  npx hyperframes add apple-terminal

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(registry): remove placeholder preview URLs for unrendered Apple Terminal themes

The 8 themes without rendered videos (clear-dark, homebrew, novel,
ocean, pro, red-sands, silver-aerogel, solid-colors) had preview.video
URLs pointing to non-existent S3 objects, returning 403. Removed the
preview field from their registry-item.json and the video embed from
their MDX pages until renders are available.

The 4 themes with uploaded videos (basic, clear-light, grass, man-page)
retain their preview URLs and are live on CDN.

* fix(registry): add apple-terminal tag so npx hyperframes add apple-terminal works

* feat(registry): render + upload all 12 Apple Terminal preview videos to CDN

Rendered the 8 missing themes (clear-dark, homebrew, novel, ocean, pro,
red-sands, silver-aerogel, solid-colors) using npx hyperframes@latest
render and uploaded to the hyperframes CDN. All 12 themes now have
live preview.video URLs and video embeds in their MDX pages.

All 12 CDN URLs return 200.

* style: format Apple Terminal HTML and JSON files with oxfmt

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-02 12:12:46 -04:00
Miguel Ángel 5245e19062 feat(registry): add code snippet blocks with VS Code workbench (#1113)
* feat(registry): add VS Code theme visualizer example

Full VS Code workbench recreation with per-character typing animation
across 12 built-in themes. Includes activity bar, sidebar, tabs,
editor with line-by-line cursor tracking, terminal panel, and status
bar — all driven by official VS Code theme JSON files.

Themes: Dark Modern, Dark 2026, Dark+, Light Modern, Light 2026,
Light+, Visual Studio Dark, Visual Studio Light, High Contrast,
High Contrast Light, Solarized Light, Monokai.

Includes build scripts to regenerate compositions from theme JSON.

* feat(registry): add 12 code snippet blocks for hyperframes add code

Individual blocks for each VS Code built-in theme, all tagged "code"
so `npx hyperframes add code` installs the full set.

Each block is a self-contained VS Code workbench with per-character
typing animation, activity bar, sidebar, tabs, terminal, and status
bar driven by official theme JSON data.

* docs: add mdx pages for code snippet blocks and example

- 12 block doc pages under catalog/blocks/code-snippet-*
- "Code Snippets" nav group in docs.json
- vscode-theme-visualizer entry in examples.mdx

* docs: revert examples.mdx — code snippets belong in catalog only

* docs: drop redundant 'Code Snippet' prefix from sidebar titles

* docs: add video previews to code snippet catalog pages

* style: format HTML, CSS, and MJS files for CI

* fix: address review feedback — build pipeline, LICENSE, dead code, nav order

1. Build script now regenerates both example compositions AND published
   blocks in registry/blocks/code-snippet-*/, keeping them in sync.
2. Add MIT LICENSE for vendored VS Code theme JSONs (microsoft/vscode).
3. Remove dead `chars` variable from runtime, build script, all blocks,
   and all example compositions.
4. Alphabetize Code Snippets nav group in docs.json to match catalog
   convention.

* style: format all build-generated files (render-entries, CSS, index)
2026-05-28 16:02:44 -04:00
Miguel ÁngelandClaude Sonnet 4.6 55c4a11884 docs: document feedback collection — cadence, data, opt-out (#1111)
* docs: document feedback collection — cadence, data, opt-out

Adds guides/feedback.mdx covering: when CLI and Studio prompts
appear (render cadence, session cadence), what data is collected
(PostHog survey fields, doctor_summary shape), what is not
collected, the hyperframes feedback command for manual/agent
submission, agent runtime detection and structured hint,
config file fields, and all opt-out paths (HYPERFRAMES_NO_TELEMETRY,
DO_NOT_TRACK, CI guard, --quiet).

Also adds hyperframes feedback command entry to packages/cli.mdx
(Utilities tab, alongside telemetry) and registers guides/feedback
in the docs.json nav.

— Magi

* docs(feedback): fix cadence, agent env vars, docker gate, telemetry scope, why-we-ask

- Cadence: 1st/16th/31st (not 15th/30th/45th) per actual code
- Agent vars: CLAUDECODE/CLAUDE_CODE_ENTRYPOINT, CODEX_THREAD_ID/CODEX_CI,
  TERM_PROGRAM=cursor, Copilot value checks; add Hermes/openclaw/Pi
- Remove docker gate claim (non-TTY only, not docker-specific)
- Telemetry disable only suppresses CLI prompt, not Studio bar
- Add why-we-ask opening section
- Remove Studio 'skip' action (CLI-only); fix 'counter resets' phrasing
- Fix 'values never read' — Cursor and Copilot do value comparisons

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs(feedback): remove invented Studio opt-out flags; document localStorage workaround

VITE_HYPERFRAMES_FEEDBACK_INTERVAL=0 falls through to default (n > 0 guard).
VITE_HYPERFRAMES_FEEDBACK feature flag doesn't exist. Bar is mounted
unconditionally. Document the localStorage key workaround instead and
note that a proper flag is a follow-up to hf#1101.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs(feedback): fix localStorage workaround — only lastPromptedAt needs to be large

Setting both keys to the same value just delays 10 sessions before the bar
reappears. Setting only lastPromptedAt to 9999999 keeps count - lastAt
negative indefinitely.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* feat(studio): add VITE_HYPERFRAMES_NO_FEEDBACK build-time disable flag

Sets isFeedbackDisabled() guard in shouldShowFeedback() — when
VITE_HYPERFRAMES_NO_FEEDBACK=1, bar never shows regardless of session count.
Updates docs to document the flag and remove the localStorage workaround.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-28 15:53:18 -04:00
James Russo 8106556e00 docs: add HyperFrames showcase (#1108) 2026-05-28 11:14:16 -07:00
James Russo ce5e872e51 feat(cli): add hyperframes cloud render/list/get/delete commands (#1110)
* feat(cli): vendor initial hyperframes cloud client codegen

Generated by experiment-framework/scripts/generate_hyperframes_cli_client.py
(see heygen-com/experiment-framework#37896). Sets up the baseline for the
sync workflow to diff against on future spec changes.

The follow-up PR adds the orchestration layer (zip + upload + poll +
download) and the user-facing 'hyperframes cloud render/list/get/delete'
commands on top of this generated client.

The fallow ignore pattern is necessary because the generated request()
method is intentionally a single switch that handles all 5 endpoints
in one place; refactoring it here would just be re-introduced on the
next codegen run.

* chore(cli): regenerate cloud client with mimeType parameter on multipart uploads

Adds optional mimeType arg to uploadAsset (and any future multipart
endpoints). Without it, FormData sends application/octet-stream which
is correct for the documented media surface (png/jpeg/mp4/etc.) but
ambiguous for the private-beta zip uploads the cloud render flow uses.
Callers that pass `mimeType: "application/zip"` tag the multipart
part with the right Content-Type so downstream proxies, WAFs, and any
future server-side change that keys off the part MIME (instead of the
current magic-byte detection) all see the intended type.

Addresses review feedback on heygen-com/experiment-framework#37896.
Generated by scripts/generate_hyperframes_cli_client.py with the
matching update to the multipart emit path.

* feat(cli): add hyperframes cloud render/list/get/delete commands

Hand-rolled orchestration layer on top of the auto-generated cloud
client (vendored in the previous PR):

- cloud render <dir>: zip via createPublishArchive → upload to
  /v3/assets → submit /v3/hyperframes/renders → poll
  /v3/hyperframes/renders/{id} every 10s (max 60min) → stream the
  signed video_url to disk.
- cloud render --no-wait: submit and exit with the render_id.
- cloud render --asset-id / --url: skip zip+upload and use a
  pre-uploaded asset or public HTTPS zip.
- cloud render --variables / --variables-file: same UX as the local
  render command; variables are validated against
  data-composition-variables only when there's a local project.
- cloud list / cloud get / cloud delete: thin wrappers around the
  matching client methods, with cursor-pagination support on list.

Auth comes from the existing cli/src/auth/ chain via cloud/auth.ts —
no new credential store, no new env var. The cloud client receives a
getAuthHeaders() callback that re-resolves credentials on every
request, so OAuth refreshes mid-poll are picked up automatically.

Also extracts a parent-scoped path lookup in help.ts so 'cloud render
--help' surfaces the right examples instead of falling through to the
top-level 'render' command's examples.

* fix(cli): address 15 code-review findings on cloud commands

Correctness fixes
- delete: require --no-confirm when stdin isn't a TTY OR --json is
  passed; previously both silently auto-bypassed the irreversible-
  delete prompt. Explicit decline now exits 2 (distinct from API/system
  errors which still exit 1).
- render: mutex check now counts the positional dir alongside
  --asset-id / --url; `cloud render ./foo --asset-id X` now errors
  instead of silently dropping the dir.
- render: docstring updated — only --no-wait short-circuits the poll
  loop; --callback-url is independent (webhook fires either way).
- render: removed dead try/catch around resolveProject (it calls
  process.exit, never throws). resolveVariablesAndValidateIfLocal also
  takes the resolved project source instead of re-parsing args.
- render: createPublishArchive errors now surface via errorBox instead
  of bubbling a raw stack trace past citty.
- help: loadExamples now only catches ERR_MODULE_NOT_FOUND; real load
  errors (syntax error, broken import) propagate so a broken
  cloud/render.ts no longer silently shows the local render command's
  examples. Also skips the parent-scoped lookup when parentName is the
  root command ("hyperframes").
- list: fetchAll gained a 50-page safety cap + duplicate-cursor
  detection so a buggy backend serving the same next_token on a loop
  can't OOM the CLI.
- download: drain await now listens for error / close / abort so a
  failing write stream (ENOSPC, AbortSignal) rejects promptly instead
  of hanging forever. Partial files are unlinked on any error so the
  caller never observes a truncated MP4. content-length is verified
  against the actual byte count.
- poll: default sleep is abort-aware so Ctrl+C feels immediate instead
  of waiting out the full interval.
- pollWithProgress: ANSI carriage-return redraws now gated on
  process.stdout.isTTY — non-TTY runs (CI, file redirects) emit one
  line per status transition instead of polluting the log with
  literal escape codes.

Cloud client: 401-retry-with-refresh
- createCloudClient now wraps the generated client with a Proxy that
  catches HyperframesApiError(status=401), force-refreshes the OAuth
  token via forceRefreshCredentials, and retries the call exactly
  once. Mirrors AuthClient's onUnauthenticatedRefresh so server-side
  revocations and clock-skew rejections recover automatically.
- auth.ts gained forceRefreshCredentials() and now updates expires_at
  on the refreshed credential it returns (fixed stale-expiry race).

Shared helpers
- cloud/errors.ts: reportApiError(stage, err, opts) is the single
  error-funnel. ERROR_CODE_HINTS now applies to every subverb — fixes
  hyperframes_render_not_found being unreachable from get/delete and
  cuts ~70 LOC of duplicated try/catch/instanceof from render/list/
  get/delete.
- cloud/parsing.ts: parseIntFlag / parseNumericFlag / parseEnumFlag
  strict-mode parsers reject trailing garbage that Number.parseInt
  silently accepts.
- cloud/ansi.ts: stripAnsi / visibleLength / padEndVisible — covers
  ESC + 24-bit truecolor (c.accent palette) instead of the previous
  regex which undercounted overhead and missed truecolor.

JSON-output consistency + _meta envelope
- Every cloud subverb's --json output now goes through withMeta(...)
  so it carries the standard _meta envelope documented in cli.mdx.
- Single-render outputs use {render: detail} across get, delete,
  render-no-wait, render-failed, and render-success. list uses
  {renders: [...], has_more, next_token?}. delete adds deleted: true.

Tests
- 25 new tests across ansi.test.ts, parsing.test.ts, plus truncation
  + abort-cleanup tests for download.test.ts.
- 589 / 589 total CLI tests pass.

* fix(cli): address Vai's review on cloud commands

- render: pass mimeType: "application/zip" to uploadAsset so the
  multipart Content-Type is correct (was application/octet-stream).
  Server currently magic-byte-detects from file bytes so this is
  belt-and-suspenders today, but any downstream proxy / WAF / future
  server change that keys off the part MIME now sees the intended
  type instead of relying on detection.
- render: poll error path now surfaces "Resume with: hyperframes
  cloud get <renderId>" via reportApiError's new `suggestion`
  option, matching the PollTimeoutError handler. The server-side
  render keeps running through a transient 5xx; the user just
  needs the right command to pick it back up.
- list: fetchAll now errorBox-exits on the malformed
  {has_more: true, next_token: null} shape instead of silently
  returning a truncated list (matching the duplicate-cursor guard).
- download: closeFile now listens for 'error' on the write stream
  in addition to the end() callback, so a late ENOSPC during flush
  doesn't leak an unhandled error onto the stream and resolves the
  finally promptly.
- errors: reportApiError accepts an optional `suggestion` that's
  used as the errorBox third line when no code-specific hint
  matches — gives callers a place to surface always-actionable
  recovery context.
- docs(cli): document --idempotency-key as the safe-retry mechanism
  for the upload step. The 401-retry Proxy replays POST requests
  on a stale token; without an idempotency key, the upload may
  land twice. A UUID per logical render is the recommended pattern.
2026-05-28 14:10:05 -04:00
James Russo b9dbafdf6a feat(cli): add hyperframes auth login --api-key, status, logout (#1081)
## What

Introduces the `hyperframes auth` command group + a shared credential
store library that hyperframes-CLI and heygen-cli will both read from.

- `hyperframes auth login --api-key` saves a HeyGen API key to
  `~/.heygen/credentials.json` (stdin pipe or hidden-input prompt).
- `hyperframes auth status` resolves the active credential (env vars
  → file) and verifies it against `GET /v3/users/me`, printing
  identity + billing.
- `hyperframes auth logout` removes the credential (`--keep-api-key`
  drops only the OAuth block).

Internals (`packages/cli/src/auth/`):
- `paths.ts` — `~/.heygen` layout, `HEYGEN_CONFIG_DIR` override.
- `store.ts` — read/write `credentials.json` (file 0600, dir 0700)
  with legacy single-line plaintext fallback so existing heygen-cli
  users don't lose their session.
- `resolver.ts` — chain: `HEYGEN_API_KEY` → `HYPERFRAMES_API_KEY` →
  file (unexpired OAuth wins over api_key).
- `client.ts` — hand-written typed wrapper for `GET /v3/users/me`
  (intentionally not OpenAPI codegen — single endpoint).
- `errors.ts` — typed `AuthError` with discriminating `code`.

## Why

This is the foundation for `hyperframes cloud render`. Splitting it
out keeps the cloud-render PR small and lets users sign in today.

The plan originally called for a library-only PR followed by a
commands PR. The `fallow` dead-code gate flagged the library-only
shape as unused exports, so I bundled them — the library and its
first consumers ship together. PR 3 (OAuth PKCE) and PR 4
(heygen-cli read-side JSON support) follow.

## How

- Credential file format: JSON with optional `api_key` + `oauth`
  blocks. Both CLIs read it; the resolver picks the freshest valid
  credential.
- Auth header selection happens in the HTTP client: OAuth →
  `Authorization: Bearer ...`, API key → `x-api-key: ...`.
- `HEYGEN_API_URL` lets dev testing target `api.dev.heygen.com`
  without rebuilding.
- The new `auth` command lazy-loads its subverbs (same pattern as
  `lambda`).

## Test plan

- [x] Unit tests added (`vitest`) for paths, store, resolver,
      client, and errors — 45 tests, all green.
- [x] `bunx tsc --noEmit -p packages/cli/tsconfig.json` clean.
- [x] `bunx oxlint` + `bunx oxfmt --check` clean.
- [x] `bunx fallow audit --base origin/main --fail-on-issues` —
      zero new findings.
- [ ] Smoke test against dev API:
      `HEYGEN_API_URL=https://api.dev.heygen.com hyperframes auth login --api-key`
      then `hyperframes auth status`.
2026-05-28 01:48:25 -04:00
James 8a9291c434 fix(cli): address code-review findings on auth PR 2026-05-28 05:39:24 +00:00
Miguel Ángel 0e052e42d2 fix(engine): support AMD AMF GPU encoding 2026-05-26 13:35:55 -04:00
Miguel Ángel 68fce93a49 Merge pull request #1041 from kiyeonjeon21/docs/rendering-comparison-license
docs: update rendering comparison and license wording
2026-05-24 23:51:47 -04:00
Miguel Ángel 4913bf3782 feat(registry): refine iOS Liquid Glass home screen 2026-05-23 20:52:30 -04:00
Miguel Ángel f63c2d40fb docs: remove stale liquid glass catalog entry 2026-05-23 19:49:56 -04:00
Miguel Ángel 3224a5d581 feat(registry): polish Liquid Glass catalog blocks 2026-05-23 19:34:00 -04:00
Kiyeon Jeon 711c4ff9f9 docs: update rendering comparison and license wording 2026-05-23 17:20:18 +09:00
Miguel Ángel 06e4db8e7b Merge pull request #1036 from heygen-com/feat/registry-parallax-zoom-unzoom
feat(registry): add parallax-zoom and parallax-unzoom components
2026-05-23 01:48:34 +02:00
JamesandClaude Opus 4.7 0c6012a2ec feat(telemetry): fingerprint sandbox runtime and agent vendor
Add two new properties to every CLI telemetry event so we can tell
managed-sandbox traffic (Codex Cloud, Claude Code Web, etc.) apart from
real developer laptops without geolocation guesswork:

- sandbox_runtime: 'gvisor' | 'firecracker' | 'docker' | 'kvm' | 'wsl' | null
  gVisor detected via kernel string ('4.19.0-gvisor' or legacy Sentry
  '4.4.0') + /proc/version. Firecracker via /dev/vsock + DMI sys_vendor.
  Docker reuses the existing /.dockerenv + cgroup probe.

- agent_runtime: claude_code | codex | cursor | copilot_agent | jules
  | replit | devin | aider | gemini_cli | hermes | openclaw | null
  Detected by the EXISTENCE of well-known vendor env vars only — values
  are never read. Hermes rule keys on HERMES_QUIET=1 (set unconditionally
  at hermes-agent/cli.py:50). openclaw rule keys on OPENCLAW_STATE_DIR
  or OPENCLAW_CONFIG_PATH (set explicitly in the spawned child env at
  openclaw/extensions/qa-matrix/src/runners/contract/scenario-runtime-cli.ts).

Drive-by cleanups required by fallow because system.ts and client.ts
fall into the audit scope of this PR:
- Extract detectWSL into platform.ts to break the system.ts ↔ agent_runtime.ts cycle.
- Refactor detectCI / getCIName into a single CI_PROVIDERS table.
- Dedupe flush / flushSync via a shared drainQueueToPayload helper.

Privacy posture unchanged: HYPERFRAMES_NO_TELEMETRY=1 still opts out;
disclosure in docs/packages/cli.mdx updated to enumerate the new fields.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 19:10:30 -04:00
Miguel Ángel 5637a48c4c chore(docs): regenerate catalog pages
Re-ran generate-catalog-pages.ts — picks up updated descriptions,
video embeds for existing components, and the renamed caption-texture
entry.
2026-05-22 18:43:13 -04:00
Miguel ÁngelandKanyini babf9dc15a feat(registry): add parallax-zoom and parallax-unzoom components
Two companion components inspired by the eBay Playbook hero transition:

- parallax-zoom: center card scales up to fill the frame while siblings
  parallax outward. Single CSS variable (--pz-progress 0→1), fully
  seekable and deterministic.

- parallax-unzoom: the reverse — focus card starts at full-frame scale
  and shrinks back into its grid position while siblings parallax inward.
  Uses --pu-progress with the pu prefix to avoid variable collisions when
  both components live in the same composition.

Designed to chain: zoom INTO a card in scene 1, unzoom OUT of it in
scene 2 to reveal a fresh grid underneath.

Includes demo compositions, registry manifests, and catalog pages.
Preview assets rendered and uploaded to CDN.

Co-authored-by: Kanyini <onebenson@gmail.com>
2026-05-22 18:42:50 -04:00
Miguel Ángel 215811334f fix(producer): accept plain integer fps in createRenderJob
The rational `Fps = { num, den }` refactor in 5dcc89c broke callers
passing `fps: 30` (the form documented in every code example and used
by external consumers). FFmpeg received `undefined/undefined` as the
framerate, causing a cryptic exit-code error.

Add `FpsInput = number | Fps` and `toFps()` normalizer in
@hyperframes/core. `createRenderJob` now accepts both forms —
plain integers are promoted to `{ num, den: 1 }` at the boundary;
`RenderConfig.fps` stays strict `Fps` internally so no downstream
code changes.

Also fixes the producer and engine docs, which showed phantom
`input`/`output` fields on `createRenderJob` and a wrong
`executeRenderJob(job)` signature (missing `projectDir`/`outputPath`
args).

Closes #1031
2026-05-22 13:35:16 -04:00
Miguel Ángel b58a81160e Merge pull request #933 from heygen-com/05-18-feat_registry_add_blend-difference_text_effect_component
feat(registry): add blend-difference text effect component
2026-05-21 21:28:56 +02:00
James ce95c9aea0 docs(nav): consolidate deploy pages into one sidebar group 2026-05-19 21:11:08 -04:00
James 8080e1f920 docs(concepts): note that media data-duration can be variable-driven 2026-05-19 20:47:46 -04:00
James d28c082416 docs(concepts): clarify what can and can't be a variable 2026-05-19 20:47:46 -04:00
James 480d0cfa5a docs(deploy): templates-on-lambda guide for personalised video at scale
User-facing guide for the automated template-rendering pipeline now
shippable end-to-end after PRs 9.1-9.4:

  - What a template is (composition + data-composition-variables)
  - Declaring variables (syntax, types, defaults, getVariables())
  - Local iteration loop (hyperframes render --variables / --variables-file
    / --strict-variables)
  - Deploying to Lambda (pointers to deploy guide + sites create)
  - Single personalised render (lambda render --variables)
  - Batch pipeline (lambda render-batch --batch users.jsonl, with a worked
    5-row example, manifest output, progress polling, --dry-run)
  - Programmatic via SDK (TypeScript example with deploySite +
    Promise.all(renderToLambda))
  - Working with large variables (the 256 KiB Step Functions ceiling,
    URL-your-assets convention, the one-line escape note for genuine
    >256 KiB cases)
  - Cost + scale considerations (Lambda concurrency, max-parallel-chunks
    vs max-concurrent, in-process vs distributed crossover)
  - Migrating from @remotion/lambda inputProps (side-by-side table; same
    256 KiB cap and same URL-your-assets convention, so migration is
    mechanical)

Includes a Mermaid architecture diagram for the site-upload-once +
N-execution fan-out flow at the top.

Adds the guide to the Deploy navigation group in docs.json (between
the existing aws-lambda and migrating-to-hyperframes-lambda pages).

Phase 9 PR 9.5 of the distributed rendering plan — the load-bearing
artifact for the user-facing pitch.
2026-05-19 19:54:30 -04:00
James f0a2740f6e feat(cli): hyperframes lambda render-batch verb
New subcommand for automated template-rendering pipelines. Given a
project dir + a JSONL batch file, fans out N personalised renders by
calling renderToLambda once per batch row with per-entry variables and
outputKey:

  hyperframes lambda render-batch ./my-template \
    --batch ./users.jsonl \
    --width 1920 --height 1080 \
    --max-concurrent 10

JSONL format (one JSON object per line):

  {"outputKey": "renders/alice.mp4", "variables": {"name": "Alice"}}
  {"outputKey": "renders/bob.mp4",   "variables": {"name": "Bob"}}

The verb deploys the site once and reuses it across renders (--site-id
skips the deploy when the project was pre-uploaded). Concurrent Step
Functions starts are capped at --max-concurrent (default 50) via a
semaphore so a 10 000-entry batch doesn't try to spawn 10 000
executions simultaneously and trip the AWS account's concurrent-
execution quota.

Per-entry results land in a manifest (one row per input line) with
executionArn + status. --json emits the manifest as machine-readable
JSON. --dry-run prints the manifest with status: "would-invoke" for
every entry without calling AWS, so callers can lint their batch file
before paying for N executions.

Variables in each batch entry pre-validate against the composition's
data-composition-variables declaration (mirroring the local
hyperframes render UX). --strict-variables aborts the run on the first
failing entry before any AWS call. The reportVariableIssues helper from
PR 9.3 is reused so the warning format matches the single-render path
exactly.

Distinction from --max-parallel-chunks: --max-concurrent caps
ORCHESTRATOR-side fan-out (how many StartExecution calls run at once);
--max-parallel-chunks caps chunks PER render. AWS account-level Lambda
concurrent-execution limits live one level up and render-batch can't
enforce those; pick --max-concurrent based on your account quota +
the reserved concurrency you provisioned via lambda deploy.

Tests cover the concurrency-cap semaphore (preserve-order,
peak-in-flight, empty-input, limit > inputs.length, propagate
rejection) and the JSONL parser (blank-line handling, malformed JSON,
missing outputKey, non-object variables).

Phase 9 PR 9.4 of the distributed rendering plan.
2026-05-19 19:54:30 -04:00
James cb948d5fcf feat(cli): hyperframes lambda render --variables / --variables-file / --strict-variables
Mirror the local hyperframes render variables UX on the Lambda CLI:

- --variables '<json>'       inline JSON object of variable values
- --variables-file <path>    path to a JSON file with variable values
- --strict-variables          fail on type/declared-mismatch (warn by default)

Resolution + validation logic is hoisted to packages/cli/src/utils/variables.ts
so both surfaces share one parser. The new reportVariableIssues helper formats
the warning block + handles --strict-variables exit, deduping the per-CLI
issue-handling block.

Variables flow into SerializableDistributedRenderConfig.variables and reach
every chunk worker via the path PR 9.1 + 9.2 wired up (plan() →
meta/encoder.json → renderChunk() → window.__hfVariables). Pre-validation
against the composition's data-composition-variables declaration runs only
when the project's index.html is on disk — --site-id pointing at a
pre-uploaded site that was packaged elsewhere skips the check, matching how
the local CLI treats unreadable index files.

The render.ts re-exports of parseVariablesArg / resolveVariablesArg /
validateVariablesAgainstProject are dropped; the matching tests move to
packages/cli/src/utils/variables.test.ts where the implementations now live.

Docs: docs/packages/cli.mdx adds a section on --variables / --variables-file /
--strict-variables for lambda render, including the 256 KiB Step Functions
execution-input cap and a pointer to the upcoming templates-on-lambda guide
(PR 9.5).

Phase 9 PR 9.3 of the distributed rendering plan.
2026-05-19 19:54:30 -04:00
Miguel Ángel 1d51a8a975 docs: add setup guides for Google Antigravity and GitHub Copilot CLI (#960)
## Summary

Closes #744 — adds dedicated setup guides for two AI coding tools that were missing from the documentation.

- **`docs/guides/antigravity.mdx`** — Google Antigravity IDE guide covering skills installation (workspace + global), semantic skill matching, Manager view parallelism for multi-scene videos, MCP alternative, and CLAUDE.md compatibility
- **`docs/guides/copilot-cli.mdx`** — GitHub Copilot CLI guide covering skills installation, slash command invocation, `/skills` management commands, agent mode for multi-step tasks, and MCP alternative
- **`docs/quickstart.mdx`** — updated agent list to mention both new tools with links to their guides
- **`docs/guides/prompting.mdx`** — updated description to include both tools
- **`docs/docs.json`** — added both guides to the Guides navigation group

## Test plan

- [x] Verify Mintlify docs build passes (`npx mintlify dev` in `docs/`)
- [x] Check navigation: both guides appear under Documentation → Guides
- [x] Verify links from quickstart.mdx to the new guide pages resolve correctly
- [x] Review guide content for accuracy against official Antigravity and Copilot CLI documentation
2026-05-19 19:13:53 +02:00
Miguel Ángel 00cbdd1d6e docs: address PR review — fix skill paths, Copilot CLI commands, MCP flag
- 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
2026-05-19 13:02:43 -04:00
Miguel Ángel 9342d3dea8 docs: add setup guides for Google Antigravity and GitHub 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.
2026-05-19 12:44:14 -04:00
James RussoandClaude Opus 4.7 5d264e146c docs(lambda): document webm support + simplify-review fixes (#953)
* docs(lambda): document webm support in distributed mode

PR 8.4 of the WebM distributed-rendering plan (v1.5 backlog #1; see
DISTRIBUTED-RENDERING-PLAN.md §7.2). User-facing docs catch up with the
shipped capability.

Updates docs/deploy/migrating-to-hyperframes-lambda.mdx:

- "Output format" row in the migration table now lists `webm` alongside
  mp4 / mov / png-sequence with a note that webm uses libvpx-vp9 +
  closed-GOP concat-copy. HDR mp4 remains the only refused format.

- "No webm distributed" caveat replaced with "webm uses closed-GOP VP9"
  explainer covering the encoder args (`-g <chunkSize>`,
  `-keyint_min <chunkSize>`, `-auto-alt-ref 0`, `-cpu-used 2`), why
  alt-ref disable is load-bearing, and that the output preserves alpha
  via yuva420p with Opus audio.

- Migration checklist no longer asks adopters to filter out webm
  compositions; only HDR-dependent renders need to stay on the previous
  framework.

aws-lambda.mdx doesn't currently call out webm as unsupported (only HDR
in the v1 surface list), so it gets no copy edits beyond the migration
guide.

The internal planning doc (DISTRIBUTED-RENDERING-PLAN.md §7.2, §8,
§12 — kept outside the repo) gets matching updates: format support
matrix flipped ✓, v1.5 backlog #1 marked shipped, HDR promoted to the
new top item, and the rev-12 → rev-13 status line.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor: address simplify-review findings on webm stack

Folds in cleanups identified by a multi-agent code-review pass over the
4-PR webm-distributed stack:

- plan.ts: `resolveEncoderTriple()` webm case now calls
  `getEncoderPreset(quality, "webm")` for its preset string instead of
  hardcoding "good". The hardcode was wrong for `quality: "draft"`
  (`getEncoderPreset` returns "realtime" for that tier) — would have
  silently overridden the draft → realtime mapping for distributed webm
  renders.
- chunkEncoder.ts: trim the new VP9 closed-GOP comment block from ~18
  lines of WHY narration down to the 6 lines that actually explain why
  (alt-ref + cpu-used drift). Match the alpha branch's idempotent-push
  comment to the same standard.
- chunkEncoder.test.ts: drop the duplicate WHY comment that restated
  the implementation comment in plain words.
- webm-concat-copy.test.ts: rewrite the file-header docstring to
  describe the contract being tested instead of the PR-8.1-gating
  history; strip "PR 8.2 / Path A / Path B" references from error
  messages (they belong in PR bodies, not in test output). Consolidate
  the yuva420p alpha smoke into a single `it()` block (was a full
  4-test describe with duplicated setup) — the yuv420p block already
  covers the probe/decode/frame-count contract; the alpha smoke only
  needs to prove the alpha args don't break concat-copy.
- plan.test.ts: drop the "PR 8.1 proved the contract" comment.
- webm-vp9 fixture: drop the aspirational "Other webm-with-audio
  fixtures cover the mux path separately when added" sentence (no
  other fixtures exist). Regenerated the baseline via
  `docker:test:update webm-vp9` to reflect the updated comment.
- migrating-to-hyperframes-lambda.mdx: add a paragraph about
  distributed webm's perf cost — ~10-25% larger files at constant CRF
  due to forced keyframes, and slower per-chunk encode due to
  `-cpu-used 2` being more conservative than the libvpx default.

All unit tests + the webm-vp9 distributed-simulated regression still
pass after these changes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(cli): accept --format=webm in `hyperframes lambda render`

The CLI's `lambda render` subcommand's FORMATS allowlist and the
`RenderArgs.format` type still narrowed to `mp4 | mov | png-sequence`,
so even though the producer + aws-lambda packages now support webm
end-to-end, the CLI surface rejected it with `--format must be mp4|mov|
png-sequence`. Add webm to both spots and update the --help description.

Surfaced during real-AWS deploy prep — the local lambda-local /
distributed-simulated tests didn't go through the CLI so the gap went
unnoticed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(producer): font cache writes to /tmp on Lambda (read-only \$HOME)

The deterministic Google Fonts cache was rooted at
`\$HOME/.cache/hyperframes/fonts`, which fails on AWS Lambda — the
runtime's `\$HOME` resolves to a `/home/sbx_*` directory tree that's
read-only. `mkdirSync(..., { recursive: true })` can't create that
path and the plan stage trips with `ENOENT: no such file or directory,
mkdir '/home/sbx_user1051/.cache/hyperframes/fonts/space-mono'` on
every Lambda render that pulls a Google Font (i.e. every distributed
fixture using `@import url("https://fonts.googleapis.com/...")`).

Detect Lambda via `\$AWS_LAMBDA_FUNCTION_NAME` and route the cache to
`tmpdir()/hyperframes/fonts` in that case. Lambda's `/tmp` survives
across invocations on a warm container, so cache hit rate is the same
as non-Lambda runs. Also honor an explicit
`\$HYPERFRAMES_FONT_CACHE_DIR` override for adopters who want a
different location regardless of the runtime.

Surfaced while verifying webm distributed end-to-end on real AWS — the
same bug affects mp4 fixtures using Google Fonts; webm just happened to
be the one I tried first.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor: extract DistributedFormat type + trim font-cache resolver

Second simplify-review pass on the webm stack flagged two cleanups:

1. **`DistributedFormat` type duplicated 10 times.** Every file in the
   distributed pipeline carried its own copy of
   `"mp4" | "mov" | "png-sequence" | "webm"` — adding a new format
   meant a 10-place edit with no compile-time guarantee they stayed in
   sync. Extract a single source of truth in
   `packages/producer/src/services/distributed/shared.ts`, re-export
   from `@hyperframes/producer/distributed` and
   `@hyperframes/aws-lambda/sdk`, and have all callers pull from
   there. The aws-lambda `ALLOWED_FORMATS` runtime tuple and the CLI's
   `FORMATS` tuple now both use `satisfies readonly DistributedFormat[]`
   so the compiler enforces the runtime allowlist stays in sync with
   the type.

2. **`deterministicFonts.ts` font-cache resolver was over-commented.**
   Trim the 7-line block to 4 lines (drop the aspirational
   "and other read-only-FS execution environments" — only Lambda is
   detected — and the warm-container `/tmp` persistence narration —
   anyone reading already knows Lambda /tmp semantics). Collapse the
   two-step `if (explicit && explicit.length > 0)` into a single
   nullish-coalesce expression now that the empty-string defensive
   check is gone (`process.env.X` is `string | undefined`, no third
   shape to guard against).

Out-of-scope skips (called out by the agents, deferred):
- In-process `RenderConfig.format` and the in-process CLI's
  `render.ts` format union still carry their own inline copies. The
  union happens to coincide today but they're separate concerns —
  leaving them alone limits this PR's blast radius.
- `fontCacheDir(slug)` / `resolveFontCacheRoot()` naming asymmetry
  flagged as taste; skipping.
- Pre-existing redundant `existsSync` before `mkdirSync({ recursive:
  true })` in `fontCacheDir` — out of scope.

All tests + typecheck still pass. Lambda render still works
end-to-end (no functional changes).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* docs(lambda): drop plan-doc reference from migration checklist

PR review feedback: source/docs should not mention the
distributed-rendering planning doc. Tighten the migration checklist
sentence to describe the webm path directly rather than referencing
the doc's version label.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(producer): split resolveEncoderTriple into mp4 + non-mp4 helpers

CI Fallow audit on PR #953 flagged `resolveEncoderTriple` at CRAP 31.6 —
the function interleaved (a) mp4 codec validation + dispatch, (b) the
non-mp4 codec-rejection throw, and (c) per-format dispatch. Splitting
into `resolveMp4EncoderTriple` + `resolveNonMp4EncoderTriple` drops the
top-level function's cyclomatic complexity below the threshold while
preserving every error message and code path. Behavior unchanged.

Also extracts an `EncoderTriple` type alias so the three functions
share the return shape declaratively rather than repeating it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-19 04:11:26 -04:00
CypherPoet c088588507 docs: add canonical pipeline guide (#937)
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.
2026-05-18 16:18:54 -05:00
Vance Ingalls bed1ca653c feat(registry): add blend-difference text effect component 2026-05-18 09:15:45 -07:00
Miguel Ángel 0f1c64dcae fix: address review feedback — observability, dedup, query-strip, catalog
Review items addressed:

1. Mirror video-failure warning in beginFrame path (was screenshot-only)
2. Fix resolveProjectRelativeSrc escape-fallback to use query-stripped
   cleanSrc instead of raw src for the normalize/strip arm
3. Export prepareFlattenedInnerRoot from @hyperframes/core/compiler and
   consume in the producer instead of duplicating the implementation
4. Use typed Window cast instead of (window as any) for __hfForceTimelineRebind
5. Regenerate docs/public/catalog-index.json with all 6 map blocks
6. Restore Maps nav group in docs.json (catalog generator had merged
   them into Data)
2026-05-18 01:41:15 -04:00
Miguel Ángel fe32622748 docs: point us-map preview to new filename to bypass CDN cache 2026-05-18 01:21:35 -04:00
Miguel Ángel 4b9abaaf6f fix: deterministic stagger, lint importmap/module, cache-bust previews
- Replace from:"random" with from:"center" stagger in us-map,
  world-map, spain-map — random stagger is non-deterministic across
  parallel render workers, causing visual jumps at chunk boundaries.

- Exempt type="importmap" and type="module" inline scripts from the
  invalid_inline_script_syntax lint rule. The rule used new Function()
  to parse, which rejects import statements and JSON import maps.
  Closes #929.

- Cache-bust all map MDX preview video URLs after re-rendering with
  the deterministic stagger fix.
2026-05-18 01:18:24 -04:00
Miguel Ángel 8777c18870 docs: cache-bust us-map preview video URL 2026-05-18 01:10:19 -04:00
Miguel Ángel 27c8b68bf5 docs: switch map MDX preview URLs to S3 production paths
Assets are uploaded to static.heygen.ai — switch from local
/images/ paths back to the canonical S3 URLs for production docs.
2026-05-18 00:55:31 -04:00
Miguel Ángel ae1716d4c1 feat(registry): add spain-map block + fix MDX preview paths
New block: spain-map — animated Spain choropleth by autonomous
community using D3 conic conformal projection with GDP per capita
data and red-to-amber color scale.

Also switches all map MDX preview URLs from S3 to local paths
so they render in mintlify dev without needing S3 upload first.
2026-05-17 23:25:47 -04:00
Miguel Ángel dba158dfc1 feat(registry): add maps section with 4 new map blocks + docs
New blocks: world-map (D3 Natural Earth choropleth), us-map-bubble
(proportional city markers), us-map-hex (hexagonal tile grid),
us-map-flow (animated connection arcs between cities).

All blocks share the same dark theme and are composable — layer
bubble or flow on top of the choropleth via track indexes.

Adds "Maps" section to the catalog docs with MDX pages for all 5
map blocks (including the us-map from the previous commit).
2026-05-17 23:16:41 -04:00
Miguel Ángel 3ec0aa456f docs: point gradient-fill preview to v3 filename 2026-05-17 21:34:24 -04:00
Miguel Ángel 693876ed0e docs: cache-bust preview video URLs for updated captions
Upload re-rendered videos with -v2 filenames to bypass CloudFront
immutable cache. Replace gradient-fill with improved version from
sandbox composition.
2026-05-17 21:24:28 -04:00
Miguel Ángel 5fbbc0ce5f docs: point weight-shift preview to v2 filename to bypass CDN cache 2026-05-17 21:11:19 -04:00
Miguel Ángel c54ebd7880 docs: cache-bust preview video URLs for updated captions 2026-05-17 21:05:33 -04:00
Miguel Ángel 4e883e20f8 fix(registry): remove caption-typewriter component 2026-05-17 19:24:26 -04:00
Miguel Ángel 47c520d02e fix(registry): polish caption timing and add highlight style
- clip-wipe: slower reveal (0.3s), longer hold, smoother exit
- glitch-rgb: 2.5x larger RGB split, stronger scanlines, more dramatic jitter
- gradient-fill: smoother word transitions (0.15s), longer exit
- typewriter: extended group hold times so text lingers on screen
- weight-shift: per-word font-weight animation (200→900), was broken
  with only line-level shift that never triggered on single-line groups
- Add caption-highlight: red background sweep behind active word (TikTok-style)
- Re-rendered and uploaded preview videos for all 6 components
2026-05-17 18:42:17 -04:00
Miguel Ángel 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
2026-05-17 17:19:42 -04:00
Miguel Ángel b725066fb5 docs(registry): add caption catalog pages and overflow protection
- Add 15 .mdx doc pages under docs/catalog/components/ for all caption styles
- Add "Captions" group as first section in the Catalog tab navigation
- Add canvas-based fitFontSize to 14 caption components to prevent text overflow
- Fix parallax-layers vertical clipping by repositioning the behind safe zone
- Re-render all 15 preview videos at high quality and upload to CDN
2026-05-17 17:03:42 -04:00