Conversation
- README with hero section, quick start, HTML schema example, package overview, and Remotion comparison - MIT LICENSE (copyright HeyGen) - CONTRIBUTING.md with dev setup, commit conventions, and project structure - GitHub issue templates (bug report, feature request) and PR template - .gitignore for Node.js/TypeScript projects Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
.gitignore
Outdated
| *.mp4 | ||
| *.webm | ||
| *.mov |
There was a problem hiding this comment.
we may have some regression tests with videos in them using git lfs something we may want to allow
CONTRIBUTING.md
Outdated
|
|
||
| - [Node.js](https://nodejs.org/) 22+ | ||
| - [pnpm](https://pnpm.io/) 9+ | ||
| - [FFmpeg](https://ffmpeg.org/) (for rendering) |
There was a problem hiding this comment.
we need a version here probably ffmpeg, can we check what version
CONTRIBUTING.md
Outdated
| 3. Install dependencies: `pnpm install` | ||
| 4. Create a branch: `git checkout -b my-feature` | ||
|
|
||
| ## Development Setup |
There was a problem hiding this comment.
should we wait to add in this info/readme now or wait till we have more code in here?
README.md
Outdated
| ## Packages | ||
|
|
||
| | Package | Description | | ||
| |---------|-------------| | ||
| | `@hyperframes/core` | Types, schema, parsers, compiler, runtime, frame adapters | | ||
| | `@hyperframes/cli` | `npx hyperframes dev \| render \| validate \| init` | | ||
| | `@hyperframes/producer` | Local rendering engine (Node.js + Puppeteer + FFmpeg) | | ||
| | `@hyperframes/studio` | Browser-based preview/editor | | ||
| | `@hyperframes/mcp` | MCP server for AI agent integration | | ||
| | `create-hyperframe` | Project scaffolding (`npx create-hyperframe`) | |
There was a problem hiding this comment.
maybe we don't add this yet ? and have WIP/reminder to do this later
README.md
Outdated
|
|
||
| ## Documentation | ||
|
|
||
| Visit [hyperframes.dev](https://hyperframes.dev) for full documentation, guides, and API reference. |
- .gitignore: remove blanket video file ignores (may need LFS for regression test fixtures) - CONTRIBUTING.md: strip dev setup details until packages are ported (leave TODO) - README.md: strip packages table, comparison, requirements, docs link (leave TODO) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
vanceingalls
left a comment
There was a problem hiding this comment.
Overall this looks good — clean scaffolding, second commit addressed the earlier review comments well. A few things to consider before going public:
1. Repo URL hardcoded to heygen-com — CONTRIBUTING.md references https://github.com/heygen-com/hyperframes/issues. The launch plan listed GitHub org name as an open decision (hyperframes, hyperframes-dev, or under HeyGen org). Not a blocker for merging into a private repo, but worth deciding before launch.
2. .gitignore gaps — Missing .debug/ (producer's parity harness writes to .debug/parity-harness-ci) and *.tgz (npm pack artifacts). Minor.
3. No pnpm-workspace.yaml stub — Plan calls for a pnpm monorepo. Including the workspace config now (even with empty packages list) would make the next PR cleaner.
4. Code of Conduct — "Be respectful. We're building something together." is fine for now, but GitHub's community profile will flag it. Consider adding Contributor Covenant before going public.
5. SECURITY.md — Not needed yet, but expected for any serious OSS project before launch. How to report vulnerabilities, responsible disclosure, etc.
None of these are merge blockers — they're all "before flipping to public" items. 👍
- CODE_OF_CONDUCT.md (Contributor Covenant v2.1) - SECURITY.md (responsible disclosure policy) - pnpm-workspace.yaml stub for monorepo - .gitignore: add .debug/ and *.tgz - CONTRIBUTING.md: link to Code of Conduct Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
bugfixes for hyperframes producer
- Eliminate redundant extractGsapWindows() call (was parsing each script twice, now once) - Fix window shadowing global — renamed to win, consistent with line 655 - Split classAttr once instead of twice - Named ClipInfo type for the selector map - Moved clip map construction before the script loop (computed once) - Removed orphan block scope and #1.5 numbering Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Eliminate redundant extractGsapWindows() call (was parsing each script twice, now once) - Fix window shadowing global — renamed to win, consistent with line 655 - Split classAttr once instead of twice - Named ClipInfo type for the selector map - Moved clip map construction before the script loop (computed once) - Removed orphan block scope and #1.5 numbering Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Eliminate redundant extractGsapWindows() call (was parsing each script twice, now once) - Fix window shadowing global — renamed to win, consistent with line 655 - Split classAttr once instead of twice - Named ClipInfo type for the selector map - Moved clip map construction before the script loop (computed once) - Removed orphan block scope and #1.5 numbering Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Eliminate redundant extractGsapWindows() call (was parsing each script twice, now once) - Fix window shadowing global — renamed to win, consistent with line 655 - Split classAttr once instead of twice - Named ClipInfo type for the selector map - Moved clip map construction before the script loop (computed once) - Removed orphan block scope and #1.5 numbering
…eadless-shell The engine assumed any binary passed via PRODUCER_HEADLESS_SHELL_PATH supported the HeadlessExperimental.beginFrame CDP command. When the CLI resolved system Chrome (e.g. /usr/bin/google-chrome) instead of chrome-headless-shell, the render would silently hang for 120s then timeout — the #1 new-user friction point. Now checks the binary path for "chrome-headless-shell" before selecting beginframe capture mode. System Chrome falls back to screenshot mode which works universally. Reproducer: # On a machine with system Chrome but no chrome-headless-shell cached npx hyperframes init test --template blank --non-interactive cd test && npx hyperframes render --output out.mp4 # Was: 120s hang, then "Timed out after waiting 120000ms" # Now: renders successfully via screenshot mode
…eadless-shell The engine assumed any binary passed via PRODUCER_HEADLESS_SHELL_PATH supported the HeadlessExperimental.beginFrame CDP command. When the CLI resolved system Chrome (e.g. /usr/bin/google-chrome) instead of chrome-headless-shell, the render would silently hang for 120s then timeout — the #1 new-user friction point. Now checks the binary path for "chrome-headless-shell" before selecting beginframe capture mode. System Chrome falls back to screenshot mode which works universally. Reproducer: # On a machine with system Chrome but no chrome-headless-shell cached npx hyperframes init test --template blank --non-interactive cd test && npx hyperframes render --output out.mp4 # Was: 120s hang, then "Timed out after waiting 120000ms" # Now: renders successfully via screenshot mode
Only one cursor may be visible at a time. Multiple cursors on screen looks broken. Every other cursor must be cursor-hide. Promoted to rule #1 in the cursor section. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(skills): add gsap-effects skill with typewriter pattern
Distills typewriter text animation into a reusable reference:
basic typewriter, blinking cursor, word rotation, appending words,
and a characters-per-second timing guide. Uses GSAP TextPlugin.
Also references the new skill from compose-video.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(skills): emphasize cursor must always blink when idle and sit flush
Two key rules added to the typewriter skill:
1. Cursor must blink in every idle state (after typing, after clearing,
during hold pauses) — a solid idle cursor looks broken.
2. No whitespace between text and cursor elements in HTML — any gap
between the last character and the caret looks wrong.
Also adds cursor-hide state for multi-line handoffs and updates word
rotation example to include cursor state management.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(skills): backspace must delete from end, not front
TextPlugin's text:{value:""} removes characters from the front,
which looks wrong. Added a backspace helper that steps through
substrings from right to left using tl.call(). Updated word
rotation example to use it.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(skills): handoffs must blink before typing, use margin for spacing
Two lessons from testing:
1. Cursor handoffs need a blink pause — going hide→solid directly
skips the idle state. Pattern: hide→blink→pause→solid→type→blink.
2. Use margin-left on a wrapper span for spacing between static and
dynamic text. Flex gap spaces the cursor away, trailing spaces
collapse.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(skills): enforce single visible cursor as a hard rule
Only one cursor may be visible at a time. Multiple cursors on
screen looks broken. Every other cursor must be cursor-hide.
Promoted to rule #1 in the cursor section.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…209) ## Summary Two independent initiatives that improve agent DX and expand HyperFrames' reach. ### Initiative 1: Fix the Clip Animation Footgun - `gsap_animates_clip_element` lint rule now uses smart detection — only errors when GSAP animates `visibility` or `display` on a clip element - All other properties (opacity, transform, x, y, scale, etc.) are allowed silently - This was the #1 agent failure in QA (10/10 agents hit it on v0.2.1) ### Initiative 2: `<hyperframes-player>` Web Component - New `@hyperframes/player` package — zero dependencies, 3.3KB gzipped - Iframe-based web component with Shadow DOM for perfect isolation - Video-like API: `play()`, `pause()`, `seek()`, `currentTime`, `duration`, events - Controls overlay with play/pause, scrubber (mouse + touch), time display, auto-hide - Full docs page at `docs/packages/player.mdx` ## Before / After ### Clip animation lint **Before (10/10 agents hit this):** ``` ✗ gsap_animates_clip_element: GSAP animation targets a clip element. Selector "#title" resolves to element <div id="title" class="clip">. The framework manages clip visibility — animate an inner wrapper instead. Fix: Wrap content in a child <div> and target that with GSAP. ``` **After (only errors on actual conflicts):** ``` # This passes lint — no error: tl.from("#title", { opacity: 0, y: -50, scale: 0.8 }, 0); # This still errors — actual conflict with runtime: tl.to("#title", { visibility: "hidden" }, 3); ✗ gsap_animates_clip_element: GSAP animation sets visibility on a clip element. Fix: Remove the visibility/display tween. Use opacity for fade effects. ``` ### Embeddable player **Before:** No way to embed a composition in a web page. **After:** ```html <script src="https://cdn.jsdelivr.net/npm/@hyperframes/player"></script> <hyperframes-player src="./composition/index.html" controls></hyperframes-player> ``` ```js const player = document.querySelector('hyperframes-player'); player.play(); player.pause(); player.seek(2.5); player.addEventListener('ready', (e) => console.log('Duration:', e.detail.duration)); ``` ## Test plan - [x] 427 core tests pass (20 GSAP lint tests with smart detection) - [x] 7 player tests pass (formatTime + element registration) - [x] TypeScript compiles cleanly (core + player) - [x] Lint: GSAP animating clip with safe props → 0 errors - [x] Lint: GSAP animating clip with `visibility` → 1 error (correct) - [x] Player builds to 3.3KB gzipped ESM - [x] Lockfile updated for CI - [x] Docs page added at `docs/packages/player.mdx`
Summary
No code yet — just the repo scaffolding for review before we start porting packages.
Test plan
🤖 Generated with Claude Code