Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "hyperframes",
"version": "0.1.0",
"description": "Write HTML, render video. Compositions, GSAP and runtime adapter animations, captions, voiceovers, audio-reactive visuals, and website-to-video capture for HyperFrames.",
"description": "Write HTML, render video. Compositions, Tailwind v4 styles, GSAP and runtime adapter animations, captions, voiceovers, audio-reactive visuals, and website-to-video capture for HyperFrames.",
"author": {
"name": "HeyGen",
"email": "hyperframes@heygen.com",
Expand All @@ -14,6 +14,7 @@
"hyperframes",
"video",
"html",
"tailwind",
"gsap",
"lottie",
"three",
Expand All @@ -30,7 +31,7 @@
"interface": {
"displayName": "HyperFrames by HeyGen",
"shortDescription": "Write HTML, render video",
"longDescription": "Build videos from HTML with HyperFrames. Author compositions with HTML, CSS, GSAP, Anime.js, Lottie, Three.js, and WAAPI adapter patterns, use the CLI for init/preview/render/transcribe/tts, install reusable registry blocks and components, and turn any website into a video with the 7-step capture-to-video pipeline.",
"longDescription": "Build videos from HTML with HyperFrames. Author compositions with HTML, CSS, Tailwind v4 browser-runtime styles, GSAP, Anime.js, Lottie, Three.js, and WAAPI adapter patterns, use the CLI for init/preview/render/transcribe/tts, install reusable registry blocks and components, and turn any website into a video with the 7-step capture-to-video pipeline.",
"developerName": "HeyGen",
"category": "Design",
"capabilities": ["Read", "Write"],
Expand Down
3 changes: 2 additions & 1 deletion .cursor-plugin/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"name": "hyperframes",
"displayName": "HyperFrames by HeyGen",
"version": "0.1.0",
"description": "Write HTML, render video. Compositions, GSAP and runtime adapter animations, captions, voiceovers, audio-reactive visuals, and website-to-video capture for HyperFrames.",
"description": "Write HTML, render video. Compositions, Tailwind v4 styles, GSAP and runtime adapter animations, captions, voiceovers, audio-reactive visuals, and website-to-video capture for HyperFrames.",
"author": {
"name": "HeyGen",
"email": "hyperframes@heygen.com"
Expand All @@ -18,6 +18,7 @@
"hyperframes",
"video",
"html",
"tailwind",
"gsap",
"lottie",
"three",
Expand Down
5 changes: 1 addition & 4 deletions .github/workflows/preview-regression.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,7 @@ jobs:
run: bun run --cwd packages/producer parity:fixtures:ci

- name: Install ffmpeg
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends ffmpeg
ffmpeg -version | head -n 1
uses: FedericoCarboni/setup-ffmpeg@36c6454b5a2348e7794ba2d82a21506605921e3d # v3

- name: Set up Chrome
id: setup-chrome
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,4 @@ will not match CI. Use it only for local-only experimentation.

## Skills

Composition authoring (not repo development) is guided by skills installed via `npx skills add heygen-com/hyperframes`. See `skills/` for source. Invoke `/hyperframes`, `/hyperframes-cli`, `/hyperframes-registry`, or `/gsap` when authoring compositions. Use `/animejs`, `/css-animations`, `/lottie`, `/three`, or `/waapi` when a composition uses those first-party runtime adapters. When a user provides a website URL and wants a video, invoke `/website-to-hyperframes` — it runs the full 7-step capture-to-video pipeline.
Composition authoring (not repo development) is guided by skills installed via `npx skills add heygen-com/hyperframes`. See `skills/` for source. Invoke `/hyperframes`, `/hyperframes-cli`, `/hyperframes-registry`, `/tailwind`, or `/gsap` when authoring compositions. Use `/tailwind` for projects created with `hyperframes init --tailwind` so agents follow the pinned Tailwind v4 browser-runtime contract instead of Studio's Tailwind v3 setup. Use `/animejs`, `/css-animations`, `/lottie`, `/three`, or `/waapi` when a composition uses those first-party runtime adapters. When a user provides a website URL and wants a video, invoke `/website-to-hyperframes` — it runs the full 7-step capture-to-video pipeline.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Install the HyperFrames skills, then describe the video you want:
npx skills add heygen-com/hyperframes
```

This teaches your agent (Claude Code, Cursor, Gemini CLI, Codex) how to write correct compositions, GSAP timelines, and first-party adapter animations. In Claude Code, the skills register as slash commands — invoke `/hyperframes` to author compositions, `/hyperframes-cli` for CLI commands, `/gsap` for timeline animation help, or the adapter skills (`/animejs`, `/css-animations`, `/lottie`, `/three`, `/waapi`) when a composition uses those runtimes.
This teaches your agent (Claude Code, Cursor, Gemini CLI, Codex) how to write correct compositions, GSAP timelines, Tailwind v4 browser-runtime styles, and first-party adapter animations. In Claude Code, the skills register as slash commands — invoke `/hyperframes` to author compositions, `/hyperframes-cli` for CLI commands, `/tailwind` for `init --tailwind` projects, `/gsap` for timeline animation help, or the adapter skills (`/animejs`, `/css-animations`, `/lottie`, `/three`, `/waapi`) when a composition uses those runtimes.

For Claude Design, open [`docs/guides/claude-design-hyperframes.md`](https://github.com/heygen-com/hyperframes/blob/main/docs/guides/claude-design-hyperframes.md) on GitHub and click the download button (↓) to save it, then attach the file to your Claude Design chat. It produces a valid first draft; refine in any AI coding agent. See the [Claude Design guide](https://hyperframes.heygen.com/guides/claude-design).

Expand Down
8 changes: 7 additions & 1 deletion docs/packages/cli.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,9 @@ This is suppressed in CI environments, non-TTY shells, and when `HYPERFRAMES_NO_
# Agent mode (default) — --example is required
npx hyperframes init my-video --example blank --video video.mp4

# Include Tailwind CSS browser-runtime support
npx hyperframes init my-video --example blank --tailwind

# Human mode — interactive prompts
npx hyperframes init --human-friendly
```
Expand All @@ -157,6 +160,7 @@ This is suppressed in CI environments, non-TTY shells, and when `HYPERFRAMES_NO_
| `--example, -e` | Example to scaffold (required in default mode, interactive in `--human-friendly`) |
| `--video, -V` | Path to a video file (MP4, WebM, MOV) |
| `--audio, -a` | Path to an audio file (MP3, WAV, M4A) |
| `--tailwind` | Add Tailwind CSS browser-runtime support to scaffolded HTML |
| `--skip-skills` | Skip AI coding skills installation |
| `--skip-transcribe` | Skip automatic whisper transcription |
| `--model` | Whisper model for transcription (e.g. `small.en`, `medium.en`, `large-v3`) |
Expand All @@ -173,6 +177,8 @@ This is suppressed in CI environments, non-TTY shells, and when `HYPERFRAMES_NO_

In default (agent) mode, `--example` is required — the CLI errors with a usage example if missing. In `--human-friendly` mode, you choose interactively. When `--video` or `--audio` is provided, the CLI automatically transcribes the audio with Whisper and patches captions into the composition (use `--skip-transcribe` to disable).

`--tailwind` injects the pinned Tailwind v4 browser runtime into scaffolded HTML and exposes a `window.__tailwindReady` promise that renders wait on before capturing frame 0. Use the `/tailwind` skill when editing these projects so agents follow v4 CSS-first patterns instead of v3 `tailwind.config.js` and `@tailwind` directive patterns. The browser runtime is still intended for scaffolded projects and quick iteration; for fully offline or locked-down production renders, compile Tailwind to CSS and include the stylesheet directly.

After scaffolding, the CLI installs AI coding skills for Claude Code, Gemini CLI, and Codex CLI (use `--skip-skills` to disable). See [`skills`](#skills) command.

See [Examples](/examples) for full details.
Expand Down Expand Up @@ -716,7 +722,7 @@ This is suppressed in CI environments, non-TTY shells, and when `HYPERFRAMES_NO_
| `--codex` | Install to Codex CLI (`~/.codex/skills/`) |
| `--cursor` | Install to Cursor (`.cursor/skills/` in current project) |

Skills are fetched from GitHub and include composition authoring, GSAP animation patterns, Anime.js, CSS animation, Lottie, Three.js, and WAAPI adapter patterns, registry block/component wiring, and other domain-specific knowledge. The `init` command also offers to install skills automatically after scaffolding a project.
Skills are fetched from GitHub and include composition authoring, Tailwind v4 browser-runtime guidance, GSAP animation patterns, Anime.js, CSS animation, Lottie, Three.js, and WAAPI adapter patterns, registry block/component wiring, and other domain-specific knowledge. The `init` command also offers to install skills automatically after scaffolding a project.

#### Troubleshooting: `fatal: active post-checkout hook found during git clone`

Expand Down
2 changes: 1 addition & 1 deletion docs/quickstart.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Install the HyperFrames skills, then describe the video you want:
npx skills add heygen-com/hyperframes
```

This teaches your agent (Claude Code, Cursor, Gemini CLI, Codex) how to write correct compositions, GSAP timelines, and first-party adapter animations. In Claude Code the skills register as slash commands — `/hyperframes` for composition authoring, `/hyperframes-cli` for CLI commands, `/gsap` for timeline animation help, and `/animejs`, `/css-animations`, `/lottie`, `/three`, or `/waapi` when a composition uses those runtimes. Invoking the slash command loads the skill context explicitly, which produces correct output the first time.
This teaches your agent (Claude Code, Cursor, Gemini CLI, Codex) how to write correct compositions, GSAP timelines, Tailwind v4 browser-runtime styles, and first-party adapter animations. In Claude Code the skills register as slash commands — `/hyperframes` for composition authoring, `/hyperframes-cli` for CLI commands, `/tailwind` for `init --tailwind` projects, `/gsap` for timeline animation help, and `/animejs`, `/css-animations`, `/lottie`, `/three`, or `/waapi` when a composition uses those runtimes. Invoking the slash command loads the skill context explicitly, which produces correct output the first time.

<Note>
Claude Design uses a different entry path. Open [`docs/guides/claude-design-hyperframes.md`](https://github.com/heygen-com/hyperframes/blob/main/docs/guides/claude-design-hyperframes.md) on GitHub, click the download button (↓) to save it, then attach to your Claude Design chat. It produces a valid first draft you can refine in any AI coding agent. See the [Claude Design guide](/guides/claude-design).
Expand Down
77 changes: 77 additions & 0 deletions packages/cli/src/commands/init.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ import { existsSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import { injectTailwindBrowserScript } from "./init.js";

const cliEntry = resolve(fileURLToPath(import.meta.url), "..", "..", "cli.ts");
const tailwindScript =
'<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4.2.4/dist/index.global.js" integrity="sha384-v5YF9xS+gLRWdvrQ0u/WRbCkjSIH0NjHIPe8tBL1ZRrmI7PiSH6LLdzs0aAIMCuh" crossorigin="anonymous"></script>';

// Spawns `bun` directly because the CLI entry is a .ts file that needs a
// TypeScript-aware runtime. vitest runs under node, so `process.execPath`
Expand Down Expand Up @@ -55,6 +58,80 @@ describe("hyperframes init flag rename", () => {
}
});

it("--tailwind enables Tailwind utilities in scaffolded HTML", () => {
const dir = mkdtempSync(join(tmpdir(), "hf-init-test-"));
const target = join(dir, "proj");
try {
const res = runInit([
target,
"--example",
"blank",
"--tailwind",
"--non-interactive",
"--skip-skills",
]);
expect(res.status).toBe(0);

const html = readFileSync(join(target, "index.html"), "utf-8");
expect(html).toContain(tailwindScript);
expect(html).toContain("window.__tailwindReady");

const pkg = JSON.parse(readFileSync(join(target, "package.json"), "utf-8")) as {
scripts?: Record<string, string>;
};
expect(pkg.scripts).toMatchObject({
dev: "npx --yes hyperframes preview",
check:
"npx --yes hyperframes lint && npx --yes hyperframes validate && npx --yes hyperframes inspect",
render: "npx --yes hyperframes render",
publish: "npx --yes hyperframes publish",
});
expect(Object.keys(pkg.scripts ?? {}).sort()).toEqual(["check", "dev", "publish", "render"]);
} finally {
rmSync(dir, { recursive: true, force: true });
}
});

it("inserts Tailwind before uppercase closing head tags", () => {
const html = [
"<!doctype html>",
"<html>",
"<head>",
' <SCRIPT src="./runtime.global.js"></SCRIPT>',
"</HEAD>",
"</html>",
].join("\n");

const injected = injectTailwindBrowserScript(html);
expect(injected.indexOf(' <SCRIPT src="./runtime.global.js"></SCRIPT>')).toBeLessThan(
injected.indexOf(tailwindScript),
);
expect(injected.indexOf(tailwindScript)).toBeLessThan(injected.indexOf("</HEAD>"));
});

it("inserts Tailwind into single-line HTML heads", () => {
const html = "<!doctype html><html><head><title>x</title></head><body></body></html>";

expect(injectTailwindBrowserScript(html)).toContain(`${tailwindScript}\n</head>`);
});

it("does not duplicate Tailwind support when it is already present", () => {
const html = ["<!doctype html>", "<html>", "<head>", tailwindScript, "</head>", "</html>"].join(
"\n",
);

expect(injectTailwindBrowserScript(html)).toBe(html);
});

it("keeps the readiness shim free of render-loop APIs", () => {
const html = "<!doctype html><html><head></head><body></body></html>";
const injected = injectTailwindBrowserScript(html);

expect(injected).not.toContain("Date.now");
expect(injected).not.toContain("requestAnimationFrame");
expect(injected).not.toContain("setTimeout");
});

it("--template prints a rename hint and exits non-zero", () => {
const dir = mkdtempSync(join(tmpdir(), "hf-init-test-"));
const target = join(dir, "proj");
Expand Down
Loading
Loading