diff --git a/.claude/skills/captions b/.claude/skills/captions new file mode 120000 index 000000000..1f0835bce --- /dev/null +++ b/.claude/skills/captions @@ -0,0 +1 @@ +../../skills/captions \ No newline at end of file diff --git a/.claude/skills/compose-video b/.claude/skills/compose-video new file mode 120000 index 000000000..ae92ed1f0 --- /dev/null +++ b/.claude/skills/compose-video @@ -0,0 +1 @@ +../../skills/compose-video \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 000000000..04a5a207d --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,70 @@ +# Hyperframes + +## Skills — USE THESE FIRST + +This repo ships skills that are installed globally via `npx hyperframes skills` (runs automatically during `hyperframes init`). **Always use the appropriate skill instead of writing code from scratch or fetching external docs.** + +### HyperFrames Skills (from this repo) + +| Skill | Invoke with | When to use | +| ----------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **compose-video** | `/compose-video` | Creating ANY HTML composition — videos, animations, title cards, overlays. Contains required HTML structure, `class="clip"` rules, GSAP timeline patterns, and rendering constraints. | +| **captions** | `/captions` | Building tone-adaptive captions from whisper transcripts — style detection, per-word styling, positioning. | + +### GSAP Skills (from [greensock/gsap-skills](https://github.com/greensock/gsap-skills)) + +| Skill | Invoke with | When to use | +| ---------------------- | --------------------- | -------------------------------------------------------------------------------- | +| **gsap-core** | `/gsap-core` | `gsap.to()`, `from()`, `fromTo()`, easing, duration, stagger, defaults | +| **gsap-timeline** | `/gsap-timeline` | Timeline sequencing, position parameter, labels, nesting, playback | +| **gsap-performance** | `/gsap-performance` | Performance best practices — transforms over layout props, will-change, batching | +| **gsap-plugins** | `/gsap-plugins` | ScrollTrigger, Flip, Draggable, SplitText, and other GSAP plugins | +| **gsap-scrolltrigger** | `/gsap-scrolltrigger` | Scroll-linked animations, pinning, scrub, triggers | +| **gsap-utils** | `/gsap-utils` | `gsap.utils` helpers — clamp, mapRange, snap, toArray, wrap, pipe | + +### Why this matters + +The skills encode HyperFrames-specific patterns (e.g., required `class="clip"` on all timed elements, GSAP timeline registration via `window.__GSAP_TIMELINE`, `data-*` attribute semantics) that are NOT in generic web docs. Skipping the skills and writing from scratch will produce broken compositions. + +### Rules + +- When creating or modifying HTML compositions → invoke `/compose-video` BEFORE writing any code +- When adding captions → invoke `/captions` BEFORE writing any code +- When writing GSAP animations → invoke `/gsap-core` and `/gsap-timeline` BEFORE writing any code +- When optimizing animation performance → invoke `/gsap-performance` BEFORE making changes + +### Installing skills + +```bash +npx hyperframes skills # install all to Claude, Gemini, Codex +npx hyperframes skills --claude # Claude Code only +npx skills add greensock/gsap-skills # alternative: via skills CLI +``` + +## Project Overview + +Open-source video rendering framework: write HTML, render video. + +``` +packages/ + cli/ → hyperframes CLI (create, preview, lint, render) + core/ → Types, parsers, generators, linter, runtime, frame adapters + engine/ → Seekable page-to-video capture engine (Puppeteer + FFmpeg) + producer/ → Full rendering pipeline (capture + encode + audio mix) + studio/ → Browser-based composition editor UI +``` + +## Development + +```bash +pnpm install # Install dependencies +pnpm build # Build all packages +pnpm test # Run tests +``` + +## Key Concepts + +- **Compositions** are HTML files with `data-*` attributes defining timeline, tracks, and media +- **Frame Adapters** bridge animation runtimes (GSAP, Lottie, CSS) to the capture engine +- **Producer** orchestrates capture → encode → audio mix into final MP4 +- **BeginFrame rendering** uses `HeadlessExperimental.beginFrame` for deterministic frame capture diff --git a/README.md b/README.md index bf252c5e3..dea6c1e2e 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,40 @@ Preview instantly in the browser. Render to MP4 locally. Let AI agents compose v | [`@hyperframes/producer`](packages/producer) | Full rendering pipeline (capture + encode + audio mix) | | [`@hyperframes/studio`](packages/studio) | Browser-based composition editor UI | +## AI Agent Skills + +HyperFrames ships skills that teach AI coding agents (Claude Code, Gemini CLI, Codex, Cursor) how to write correct compositions and GSAP animations. **Use these instead of writing from scratch — they encode framework-specific patterns that generic docs don't cover.** + +### Install via CLI (recommended) + +```bash +# Install all skills (HyperFrames + GSAP) — runs automatically during `hyperframes init` +npx hyperframes skills + +# Or install to a specific agent +npx hyperframes skills --claude +npx hyperframes skills --cursor +``` + +### Or via `npx skills add` + +```bash +# HyperFrames skills (compose-video, captions) +npx skills add heygen-com/hyperframes + +# GSAP skills (gsap-core, gsap-timeline, gsap-scrolltrigger, gsap-plugins, gsap-performance, gsap-utils, gsap-react, gsap-frameworks) +npx skills add greensock/gsap-skills +``` + +### Installed Skills + +| Source | Skills | What they teach | +| ---------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- | +| **HyperFrames** | `compose-video`, `captions` | HTML composition structure, `class="clip"` rules, `data-*` attributes, timeline registration, rendering constraints | +| **[GSAP](https://github.com/greensock/gsap-skills)** | `gsap-core`, `gsap-timeline`, `gsap-performance`, `gsap-plugins`, `gsap-scrolltrigger`, `gsap-utils`, `gsap-react`, `gsap-frameworks` | Core API, timeline sequencing, ScrollTrigger, plugin usage, performance best practices | + +In Claude Code, invoke with `/compose-video`, `/captions`, `/gsap-core`, etc. + ## Documentation Full docs at [hyperframes.heygen.com](https://hyperframes.heygen.com) — includes guides, concepts, API reference, and package documentation. diff --git a/packages/cli/package.json b/packages/cli/package.json index 0973cc657..ebbc0e7a3 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -15,7 +15,7 @@ "build:fonts": "cd ../producer && tsx scripts/generate-font-data.ts", "build:studio": "cd ../studio && bun run build", "build:runtime": "tsx scripts/build-runtime.ts", - "build:copy": "mkdir -p dist/studio dist/docs dist/templates && cp -r ../studio/dist/* dist/studio/ && cp -r src/templates/blank src/templates/warm-grain src/templates/play-mode src/templates/swiss-grid src/templates/vignelli dist/templates/ && (cp src/docs/*.md dist/docs/ 2>/dev/null || true)", + "build:copy": "mkdir -p dist/studio dist/docs dist/templates dist/skills && cp -r ../studio/dist/* dist/studio/ && cp -r src/templates/blank src/templates/warm-grain src/templates/play-mode src/templates/swiss-grid src/templates/vignelli src/templates/_shared dist/templates/ && cp -r ../../skills/compose-video ../../skills/captions dist/skills/ && (cp src/docs/*.md dist/docs/ 2>/dev/null || true)", "typecheck": "tsc --noEmit" }, "dependencies": { diff --git a/packages/cli/src/commands/init.ts b/packages/cli/src/commands/init.ts index 9f707140a..3917b1a84 100644 --- a/packages/cli/src/commands/init.ts +++ b/packages/cli/src/commands/init.ts @@ -205,6 +205,22 @@ function getStaticTemplateDir(templateId: string): string { return existsSync(devPath) ? devPath : builtPath; } +function getSharedTemplateDir(): string { + const dir = dirname(fileURLToPath(import.meta.url)); + const devPath = resolve(dir, "..", "templates", "_shared"); + const builtPath = resolve(dir, "templates", "_shared"); + return existsSync(devPath) ? devPath : builtPath; +} + +function getBundledSkillsDir(): string { + const dir = dirname(fileURLToPath(import.meta.url)); + // In dev: cli/src/commands/ → ../../../../skills = repo root skills/ + // In built: cli/dist/ → skills = cli/dist/skills/ + const devPath = resolve(dir, "..", "..", "..", "..", "skills"); + const builtPath = resolve(dir, "skills"); + return existsSync(devPath) ? devPath : builtPath; +} + function patchVideoSrc( dir: string, videoFilename: string | undefined, @@ -410,6 +426,32 @@ function scaffoldProject( ), "utf-8", ); + + // Copy shared files (CLAUDE.md, AGENTS.md) for AI agent context + const sharedDir = getSharedTemplateDir(); + if (existsSync(sharedDir)) { + for (const entry of readdirSync(sharedDir, { withFileTypes: true })) { + const src = join(sharedDir, entry.name); + const dest = resolve(destDir, entry.name); + if (entry.isFile() || entry.isSymbolicLink()) { + copyFileSync(src, dest); + } + } + } + + // Copy project-level skills (.claude/skills/) for immediate availability + const skillsSrcDir = getBundledSkillsDir(); + if (existsSync(skillsSrcDir)) { + const projectSkills = ["compose-video", "captions"]; + for (const skill of projectSkills) { + const src = join(skillsSrcDir, skill); + if (existsSync(src)) { + const dest = resolve(destDir, ".claude", "skills", skill); + mkdirSync(dest, { recursive: true }); + cpSync(src, dest, { recursive: true }); + } + } + } } // --------------------------------------------------------------------------- @@ -578,9 +620,28 @@ Examples: } console.log(c.success(`Created ${c.accent(name + "/")}`)); - for (const f of readdirSync(destDir)) { + for (const f of readdirSync(destDir).filter((f) => !f.startsWith("."))) { console.log(` ${c.accent(f)}`); } + console.log(); + console.log("Next steps:"); + console.log( + ` ${c.accent(`cd ${name}`)} && ${c.accent("npx hyperframes dev")} ${c.dim("# preview in studio")}`, + ); + console.log( + ` ${c.accent(`cd ${name}`)} && ${c.accent("npx hyperframes render")} ${c.dim("# render to MP4")}`, + ); + console.log( + ` ${c.accent("npx hyperframes docs")} ${c.dim("")} ${c.dim("# learn composition syntax")}`, + ); + console.log( + ` ${c.dim("topics: data-attributes, gsap, compositions, rendering, templates, troubleshooting")}`, + ); + console.log(); + console.log( + ` ${c.dim("AI skills installed — open this folder in your AI coding agent to get started.")}`, + ); + console.log(` ${c.dim("Full docs: hyperframes.heygen.com")}`); return; } diff --git a/packages/cli/src/templates/_shared/AGENTS.md b/packages/cli/src/templates/_shared/AGENTS.md new file mode 120000 index 000000000..681311eb9 --- /dev/null +++ b/packages/cli/src/templates/_shared/AGENTS.md @@ -0,0 +1 @@ +CLAUDE.md \ No newline at end of file diff --git a/packages/cli/src/templates/_shared/CLAUDE.md b/packages/cli/src/templates/_shared/CLAUDE.md new file mode 100644 index 000000000..bffa11556 --- /dev/null +++ b/packages/cli/src/templates/_shared/CLAUDE.md @@ -0,0 +1,50 @@ +# HyperFrames Composition Project + +## Skills — USE THESE FIRST + +**Always invoke the relevant skill before writing or modifying compositions.** Skills encode framework-specific patterns (e.g., `class="clip"`, `window.__timelines`, `data-*` attributes) that are NOT in generic web docs. Skipping them produces broken compositions. + +| Skill | Command | When to use | +| -------------------- | ------------------- | ------------------------------------------------------------------------------------------------------ | +| **compose-video** | `/compose-video` | Creating or editing ANY HTML composition — videos, animations, title cards, overlays, sub-compositions | +| **captions** | `/captions` | Building captions from whisper transcripts — style detection, per-word styling | +| **gsap-core** | `/gsap-core` | GSAP tweens: `gsap.to()`, `from()`, `fromTo()`, easing, stagger, defaults | +| **gsap-timeline** | `/gsap-timeline` | Timeline sequencing, position parameter, labels, nesting | +| **gsap-performance** | `/gsap-performance` | Animation performance — transforms over layout props, will-change, batching | + +> **Skills not available?** Ask the user to run `npx hyperframes skills` and restart their +> agent session, or install manually: `npx skills add heygen-com/hyperframes` and +> `npx skills add greensock/gsap-skills`. + +## Commands + +```bash +npx hyperframes dev # preview in browser (studio editor) +npx hyperframes render # render to MP4 +npx hyperframes lint # validate compositions +npx hyperframes docs # reference docs in terminal +``` + +Available doc topics: `data-attributes`, `gsap`, `compositions`, `rendering`, `templates`, `troubleshooting` + +Full docs: [hyperframes.heygen.com](https://hyperframes.heygen.com) + +## Project Structure + +- `index.html` — main composition (root timeline) +- `compositions/` — sub-compositions referenced via `data-composition-src` +- `meta.json` — project metadata (id, name) +- `transcript.json` — whisper word-level transcript (if generated) + +## Key Rules + +1. Every timed element needs `data-start`, `data-duration`, and `data-track-index` +2. Elements with timing **MUST** have `class="clip"` — the framework uses this for visibility control +3. Timelines must be paused and registered on `window.__timelines`: + ```js + window.__timelines = window.__timelines || {}; + window.__timelines["composition-id"] = gsap.timeline({ paused: true }); + ``` +4. Videos use `muted` with a separate `