mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-08-31 02:41:44 +00:00
docs: restructure README with skills-first quick start, demo GIF, catalog, and fix pnpm refs (#277)
## What Restructures the README to lead with skills-first onboarding, adds a demo GIF, surfaces the catalog, fixes incorrect pnpm references in contributing docs, and corrects the HTML example to use actual attribute names. ## Why The README told a CLI-first story while the homepage (hyperframes.heygen.com) tells an AI-agent-first story. For a project that brands itself "built for agents," the GitHub landing page should match. Additionally, 50+ catalog blocks were invisible from GitHub, the player and shader-transitions packages were missing from the packages table, and the contributing docs referenced pnpm while the repo uses bun. ## How **README changes:** - Quick Start restructured: skills install as Option 1 (recommended), manual CLI as Option 2 - Added demo GIF rendered with HyperFrames itself (HTML + GSAP composition → MP4 → GIF) - Added Catalog section with install examples and link - Added `@hyperframes/player` and `@hyperframes/shader-transitions` to packages table - Added npm downloads badge - Fixed HTML example: `data-track` → `data-track-index`, added missing `class="clip"` on img - Condensed Skills section into a concise table - Documentation link now points to `/introduction` (Mintlify docs) instead of the landing page **testing-local-changes.mdx:** - All `pnpm` references replaced with `bun` (14 occurrences) - Path references updated from `hyperframes-oss` to `hyperframes` ## Test plan - [ ] Verify README renders correctly on GitHub (logo, badges, GIF, tables, code blocks) - [ ] Verify GIF loops and is readable at GitHub's default README width - [ ] Verify all links resolve (docs site, catalog, packages, contributing) - [ ] Read through testing-local-changes.mdx for any remaining pnpm references - [x] Documentation updated (if applicable)
This commit is contained in:
@@ -8,40 +8,54 @@
|
||||
|
||||
<p align="center">
|
||||
<a href="https://www.npmjs.com/package/hyperframes"><img src="https://img.shields.io/npm/v/hyperframes.svg?style=flat" alt="npm version"></a>
|
||||
<a href="https://www.npmjs.com/package/hyperframes"><img src="https://img.shields.io/npm/dm/hyperframes.svg?style=flat" alt="npm downloads"></a>
|
||||
<a href="LICENSE"><img src="https://img.shields.io/badge/license-Apache%202.0-blue.svg" alt="License"></a>
|
||||
<a href="https://nodejs.org"><img src="https://img.shields.io/badge/node-%3E%3D22-brightgreen" alt="Node.js"></a>
|
||||
</p>
|
||||
|
||||
**Write HTML. Render video. Built for agents.**
|
||||
<p align="center"><b>Write HTML. Render video. Built for agents.</b></p>
|
||||
|
||||
Hyperframes is an open-source video rendering framework that lets you create, preview, and render HTML-based video compositions — with first-class support for AI agents via MCP.
|
||||
<p align="center">
|
||||
<img src="docs/images/readme-demo.gif" alt="HyperFrames demo — HTML code on the left transforms into a rendered video on the right" width="800">
|
||||
</p>
|
||||
|
||||
## Why Hyperframes?
|
||||
|
||||
- **HTML-native** — AI agents already speak HTML. No React required.
|
||||
- **Frame Adapter pattern** — bring your own animation runtime (GSAP, Lottie, CSS, Three.js).
|
||||
- **Deterministic rendering** — same input = identical output. Built for automated pipelines.
|
||||
- **AI-first design** — not a bolted-on afterthought.
|
||||
Hyperframes is an open-source video rendering framework that lets you create, preview, and render HTML-based video compositions — with first-class support for AI agents.
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Option 1: With an AI coding agent (recommended)
|
||||
|
||||
Install the HyperFrames skills, then describe the video you want:
|
||||
|
||||
```bash
|
||||
npx skills add heygen-com/hyperframes
|
||||
```
|
||||
|
||||
This teaches your agent (Claude Code, Cursor, Gemini CLI, Codex) how to write correct compositions and GSAP animations. Then just prompt it:
|
||||
|
||||
> "Create a 10-second product intro video with a fade-in title, a background video, and background music"
|
||||
|
||||
The agent handles scaffolding, animation, and rendering.
|
||||
|
||||
### Option 2: Start a project manually
|
||||
|
||||
```bash
|
||||
npx hyperframes init my-video
|
||||
cd my-video
|
||||
```
|
||||
|
||||
Then open the project with your AI coding agent (Claude Code, Cursor, etc.) — it has HyperFrames skills installed and knows how to create and edit compositions.
|
||||
|
||||
```bash
|
||||
npx hyperframes preview # preview in browser (live reload)
|
||||
npx hyperframes render # render to MP4
|
||||
npx hyperframes render # render to MP4
|
||||
```
|
||||
|
||||
`hyperframes init` installs skills automatically, so you can hand off to your AI agent at any point.
|
||||
|
||||
**Requirements:** Node.js >= 22, FFmpeg
|
||||
|
||||
## Documentation
|
||||
## Why Hyperframes?
|
||||
|
||||
Full documentation at **[hyperframes.heygen.com](https://hyperframes.heygen.com)** — start with the [Quickstart](https://hyperframes.heygen.com/quickstart), then explore guides, concepts, API reference, and package docs.
|
||||
- **HTML-native** — compositions are HTML files with data attributes. No React, no proprietary DSL.
|
||||
- **AI-first** — agents already speak HTML. The CLI is non-interactive by default, designed for agent-driven workflows.
|
||||
- **Deterministic rendering** — same input = identical output. Built for automated pipelines.
|
||||
- **Frame Adapter pattern** — bring your own animation runtime (GSAP, Lottie, CSS, Three.js).
|
||||
|
||||
## How It Works
|
||||
|
||||
@@ -53,73 +67,80 @@ Define your video as HTML with data attributes:
|
||||
id="clip-1"
|
||||
data-start="0"
|
||||
data-duration="5"
|
||||
data-track="0"
|
||||
data-track-index="0"
|
||||
src="intro.mp4"
|
||||
muted
|
||||
playsinline
|
||||
></video>
|
||||
<img id="overlay" data-start="2" data-duration="3" data-track="1" src="logo.png" />
|
||||
<img
|
||||
id="overlay"
|
||||
class="clip"
|
||||
data-start="2"
|
||||
data-duration="3"
|
||||
data-track-index="1"
|
||||
src="logo.png"
|
||||
/>
|
||||
<audio
|
||||
id="bg-music"
|
||||
data-start="0"
|
||||
data-duration="9"
|
||||
data-track="2"
|
||||
data-track-index="2"
|
||||
data-volume="0.5"
|
||||
src="music.wav"
|
||||
></audio>
|
||||
</div>
|
||||
```
|
||||
|
||||
Preview instantly in the browser. Render to MP4 locally. Let AI agents compose videos using tools they already understand.
|
||||
Preview instantly in the browser. Render to MP4 locally or in Docker.
|
||||
|
||||
## Catalog
|
||||
|
||||
50+ ready-to-use blocks and components — social overlays, shader transitions, data visualizations, and cinematic effects:
|
||||
|
||||
```bash
|
||||
npx hyperframes add flash-through-white # shader transition
|
||||
npx hyperframes add instagram-follow # social overlay
|
||||
npx hyperframes add data-chart # animated chart
|
||||
```
|
||||
|
||||
Browse the full catalog at **[hyperframes.heygen.com/catalog](https://hyperframes.heygen.com/catalog/blocks/data-chart)**.
|
||||
|
||||
## Documentation
|
||||
|
||||
Full documentation at **[hyperframes.heygen.com/introduction](https://hyperframes.heygen.com/introduction)** — [Quickstart](https://hyperframes.heygen.com/quickstart) | [Guides](https://hyperframes.heygen.com/guides/gsap-animation) | [API Reference](https://hyperframes.heygen.com/packages/core) | [Catalog](https://hyperframes.heygen.com/catalog/blocks/data-chart)
|
||||
|
||||
## Packages
|
||||
|
||||
| Package | Description |
|
||||
| -------------------------------------------- | ----------------------------------------------------------- |
|
||||
| [`hyperframes`](packages/cli) | CLI — create, preview, lint, and render compositions |
|
||||
| [`@hyperframes/core`](packages/core) | Types, parsers, generators, linter, runtime, frame adapters |
|
||||
| [`@hyperframes/engine`](packages/engine) | Seekable page-to-video capture engine (Puppeteer + FFmpeg) |
|
||||
| [`@hyperframes/producer`](packages/producer) | Full rendering pipeline (capture + encode + audio mix) |
|
||||
| [`@hyperframes/studio`](packages/studio) | Browser-based composition editor UI |
|
||||
| Package | Description |
|
||||
| ---------------------------------------------------------------- | ----------------------------------------------------------- |
|
||||
| [`hyperframes`](packages/cli) | CLI — create, preview, lint, and render compositions |
|
||||
| [`@hyperframes/core`](packages/core) | Types, parsers, generators, linter, runtime, frame adapters |
|
||||
| [`@hyperframes/engine`](packages/engine) | Seekable page-to-video capture engine (Puppeteer + FFmpeg) |
|
||||
| [`@hyperframes/producer`](packages/producer) | Full rendering pipeline (capture + encode + audio mix) |
|
||||
| [`@hyperframes/studio`](packages/studio) | Browser-based composition editor UI |
|
||||
| [`@hyperframes/player`](packages/player) | Embeddable `<hyperframes-player>` web component |
|
||||
| [`@hyperframes/shader-transitions`](packages/shader-transitions) | WebGL shader transitions for compositions |
|
||||
|
||||
## AI Agent Skills
|
||||
## 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)
|
||||
HyperFrames ships [skills](https://github.com/vercel-labs/skills) that teach AI agents framework-specific patterns that generic docs don't cover.
|
||||
|
||||
```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
|
||||
npx skills add heygen-com/hyperframes # HyperFrames skills
|
||||
npx skills add greensock/gsap-skills # GSAP animation skills
|
||||
```
|
||||
|
||||
### Or via `npx skills add`
|
||||
|
||||
```bash
|
||||
# HyperFrames skills (hyperframes-compose, hyperframes-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** | `hyperframes-compose`, `hyperframes-captions`, `hyperframes-registry` | HTML composition structure, `class="clip"` rules, `data-*` attributes, timeline registration, rendering constraints, registry block/component install and wiring |
|
||||
| **[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 `/hyperframes-compose`, `/hyperframes-captions`, `/gsap-core`, etc.
|
||||
| Skill | What it teaches |
|
||||
| ------------------------------------------------- | ---------------------------------------------------------------------- |
|
||||
| `hyperframes-compose` | HTML composition structure, `data-*` attributes, timeline registration |
|
||||
| `hyperframes-captions` | Caption/subtitle authoring and transcript integration |
|
||||
| `hyperframes-registry` | Block and component installation via `hyperframes add` |
|
||||
| `gsap-core`, `gsap-timeline`, `gsap-plugins`, ... | GSAP animation API, sequencing, ScrollTrigger, performance |
|
||||
|
||||
## Contributing
|
||||
|
||||
See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines on how to contribute.
|
||||
See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
||||
|
||||
## License
|
||||
|
||||
See [LICENSE](LICENSE) for details.
|
||||
[Apache 2.0](LICENSE)
|
||||
|
||||
@@ -11,26 +11,25 @@ Build the monorepo first. Every time you change source files, rebuild before tes
|
||||
|
||||
```bash
|
||||
# From the monorepo root
|
||||
pnpm build
|
||||
bun run build
|
||||
```
|
||||
|
||||
## Option 1: pnpm link (recommended)
|
||||
## Option 1: bun link (recommended)
|
||||
|
||||
`pnpm link --global` makes the `hyperframes` binary in your `$PATH` point at your local build. It survives across terminal sessions and auto-picks up new builds without re-linking.
|
||||
`bun link` makes the `hyperframes` binary in your `$PATH` point at your local build. It survives across terminal sessions and auto-picks up new builds without re-linking.
|
||||
|
||||
```bash
|
||||
# If you previously installed hyperframes globally, remove it first —
|
||||
# a global install takes priority over pnpm link and shadows your local build.
|
||||
pnpm remove -g hyperframes 2>/dev/null || npm uninstall -g hyperframes 2>/dev/null
|
||||
# a global install takes priority over bun link and shadows your local build.
|
||||
npm uninstall -g hyperframes 2>/dev/null
|
||||
|
||||
# Link your local build
|
||||
cd packages/cli
|
||||
pnpm link --global
|
||||
bun link
|
||||
|
||||
# Verify — should print your local version AND point to the monorepo
|
||||
hyperframes --version
|
||||
which hyperframes
|
||||
# The path should contain your monorepo, NOT pnpm/global/.pnpm/hyperframes@...
|
||||
```
|
||||
|
||||
Now use `hyperframes` normally in any directory:
|
||||
@@ -40,12 +39,12 @@ cd ~/my-video-project
|
||||
hyperframes preview .
|
||||
```
|
||||
|
||||
**After every `pnpm build`** the linked binary is already up to date — no re-linking needed.
|
||||
**After every `bun run build`** the linked binary is already up to date — no re-linking needed.
|
||||
|
||||
To restore the published release when you're done:
|
||||
|
||||
```bash
|
||||
pnpm unlink --global hyperframes
|
||||
bun unlink hyperframes
|
||||
npm install -g hyperframes@latest
|
||||
```
|
||||
|
||||
@@ -55,13 +54,13 @@ If you don't want to touch your global `$PATH`, add a shell alias or call `node`
|
||||
|
||||
```bash
|
||||
# Temporary alias for your current shell session
|
||||
alias hyperframes="node /path/to/hyperframes-oss/packages/cli/dist/cli.js"
|
||||
alias hyperframes="node /path/to/hyperframes/packages/cli/dist/cli.js"
|
||||
|
||||
# Or invoke directly
|
||||
node /path/to/hyperframes-oss/packages/cli/dist/cli.js preview .
|
||||
node /path/to/hyperframes/packages/cli/dist/cli.js preview .
|
||||
```
|
||||
|
||||
Replace `/path/to/hyperframes-oss` with your actual monorepo path.
|
||||
Replace `/path/to/hyperframes` with your actual monorepo path.
|
||||
|
||||
## Option 3: npm pack (test the exact published artifact)
|
||||
|
||||
@@ -74,9 +73,9 @@ npm pack
|
||||
|
||||
# Test it in an isolated directory
|
||||
mkdir /tmp/pack-test && cd /tmp/pack-test
|
||||
npx /path/to/hyperframes-oss/packages/cli/hyperframes-<version>.tgz init my-video
|
||||
npx /path/to/hyperframes/packages/cli/hyperframes-<version>.tgz init my-video
|
||||
cd my-video
|
||||
npx /path/to/hyperframes-oss/packages/cli/hyperframes-<version>.tgz preview .
|
||||
npx /path/to/hyperframes/packages/cli/hyperframes-<version>.tgz preview .
|
||||
```
|
||||
|
||||
## Testing the fix branches
|
||||
@@ -105,26 +104,23 @@ Common test scenarios:
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Changes not reflected after `pnpm build`**
|
||||
**Changes not reflected after `bun run build`**
|
||||
|
||||
The CLI binary is a single bundled file at `packages/cli/dist/cli.js`. If your change is in `@hyperframes/core` or another workspace package, make sure `pnpm build` rebuilt _all_ packages — the CLI bundles its dependencies at build time.
|
||||
The CLI binary is a single bundled file at `packages/cli/dist/cli.js`. If your change is in `@hyperframes/core` or another workspace package, make sure `bun run build` rebuilt _all_ packages — the CLI bundles its dependencies at build time.
|
||||
|
||||
**`hyperframes` still shows the old version / old UI**
|
||||
|
||||
A globally installed `hyperframes` package shadows `pnpm link`. Check which binary is active:
|
||||
A globally installed `hyperframes` package shadows `bun link`. Check which binary is active:
|
||||
|
||||
```bash
|
||||
which hyperframes
|
||||
# BAD: /Users/you/Library/pnpm/hyperframes → pnpm/global/.pnpm/hyperframes@0.x.x/...
|
||||
# GOOD: /Users/you/Library/pnpm/hyperframes → your-monorepo/packages/cli/dist/cli.js
|
||||
```
|
||||
|
||||
If it points to the global store, remove the global install and re-link:
|
||||
If it points to a global store rather than your monorepo, remove the global install and re-link:
|
||||
|
||||
```bash
|
||||
pnpm remove -g hyperframes
|
||||
npm uninstall -g hyperframes # in case it was installed via npm
|
||||
cd packages/cli && pnpm link --global
|
||||
npm uninstall -g hyperframes
|
||||
cd packages/cli && bun link
|
||||
```
|
||||
|
||||
**Port already in use**
|
||||
|
||||
@@ -0,0 +1,505 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=1920, height=1080" />
|
||||
<title>HyperFrames README Demo</title>
|
||||
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&family=JetBrains+Mono:wght@400;500;600&display=block"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<style>
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||||
html, body {
|
||||
margin: 0;
|
||||
width: 1920px;
|
||||
height: 1080px;
|
||||
overflow: hidden;
|
||||
background: #0a0a0f;
|
||||
font-family: "Inter", -apple-system, sans-serif;
|
||||
color: #fff;
|
||||
}
|
||||
#root {
|
||||
width: 1920px;
|
||||
height: 1080px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* ── Subtle grid background ── */
|
||||
.bg-grid {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background-image:
|
||||
linear-gradient(rgba(255,255,255,0.03) 1px, transparent 1px),
|
||||
linear-gradient(90deg, rgba(255,255,255,0.03) 1px, transparent 1px);
|
||||
background-size: 60px 60px;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
/* ── Gradient accent orbs ── */
|
||||
.accent-orb {
|
||||
position: absolute;
|
||||
width: 800px;
|
||||
height: 800px;
|
||||
border-radius: 50%;
|
||||
filter: blur(120px);
|
||||
opacity: 0;
|
||||
}
|
||||
.orb-1 {
|
||||
background: radial-gradient(circle, rgba(116, 225, 185, 0.25), transparent 70%);
|
||||
top: -200px;
|
||||
right: -100px;
|
||||
}
|
||||
.orb-2 {
|
||||
background: radial-gradient(circle, rgba(106, 220, 255, 0.2), transparent 70%);
|
||||
bottom: -300px;
|
||||
left: -100px;
|
||||
}
|
||||
|
||||
/* ── Code panel ── */
|
||||
.code-panel {
|
||||
position: absolute;
|
||||
top: 100px;
|
||||
left: 80px;
|
||||
width: 840px;
|
||||
height: 640px;
|
||||
background: rgba(20, 20, 30, 0.9);
|
||||
border: 1px solid rgba(255,255,255,0.08);
|
||||
border-radius: 16px;
|
||||
padding: 28px 32px;
|
||||
opacity: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
.code-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.code-dot { width: 12px; height: 12px; border-radius: 50%; }
|
||||
.code-dot:nth-child(1) { background: #ff5f57; }
|
||||
.code-dot:nth-child(2) { background: #febc2e; }
|
||||
.code-dot:nth-child(3) { background: #28c840; }
|
||||
.code-filename {
|
||||
font-family: "JetBrains Mono", monospace;
|
||||
font-size: 14px;
|
||||
color: rgba(255,255,255,0.4);
|
||||
margin-left: 12px;
|
||||
}
|
||||
.code-content {
|
||||
font-family: "JetBrains Mono", monospace;
|
||||
font-size: 18px;
|
||||
line-height: 1.7;
|
||||
white-space: pre;
|
||||
}
|
||||
.code-line { display: block; opacity: 0; }
|
||||
.c-tag { color: #7dd3fc; }
|
||||
.c-attr { color: #c084fc; }
|
||||
.c-val { color: #86efac; }
|
||||
.c-str { color: #fbbf24; }
|
||||
.c-cmt { color: rgba(255,255,255,0.3); font-style: italic; }
|
||||
|
||||
/* ── Output panel ── */
|
||||
.output-panel {
|
||||
position: absolute;
|
||||
top: 100px;
|
||||
right: 80px;
|
||||
width: 840px;
|
||||
height: 640px;
|
||||
border-radius: 16px;
|
||||
overflow: hidden;
|
||||
opacity: 0;
|
||||
border: 1px solid rgba(255,255,255,0.08);
|
||||
}
|
||||
.output-label {
|
||||
position: absolute;
|
||||
top: 14px;
|
||||
right: 18px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: rgba(255,255,255,0.25);
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 2px;
|
||||
z-index: 10;
|
||||
}
|
||||
.preview-stage {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%);
|
||||
}
|
||||
.preview-content { text-align: center; }
|
||||
.preview-title {
|
||||
font-size: 64px;
|
||||
font-weight: 800;
|
||||
line-height: 1.2;
|
||||
opacity: 0;
|
||||
}
|
||||
.preview-title .line-1 { display: block; color: #fff; }
|
||||
.preview-title .line-2 { display: block; color: #74e1b9; font-size: 72px; }
|
||||
.preview-subtitle {
|
||||
font-size: 22px;
|
||||
color: rgba(255,255,255,0.5);
|
||||
margin-top: 16px;
|
||||
opacity: 0;
|
||||
}
|
||||
.preview-btn {
|
||||
margin-top: 28px;
|
||||
padding: 14px 36px;
|
||||
background: linear-gradient(135deg, #74e1b9, #6adcff);
|
||||
border-radius: 30px;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #0a0a0f;
|
||||
opacity: 0;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/* ── Arrow ── */
|
||||
.arrow {
|
||||
position: absolute;
|
||||
top: 395px;
|
||||
left: 938px;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
/* ── Showcase strip ── */
|
||||
.showcase-strip {
|
||||
position: absolute;
|
||||
bottom: 50px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 170px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 20px;
|
||||
opacity: 0;
|
||||
}
|
||||
.showcase-card {
|
||||
width: 240px;
|
||||
height: 150px;
|
||||
border-radius: 12px;
|
||||
overflow: hidden;
|
||||
opacity: 0;
|
||||
transform: translateY(30px);
|
||||
border: 1px solid rgba(255,255,255,0.1);
|
||||
position: relative;
|
||||
}
|
||||
.card-label {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
padding: 8px 12px;
|
||||
background: linear-gradient(transparent, rgba(0,0,0,0.85));
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: rgba(255,255,255,0.8);
|
||||
}
|
||||
|
||||
/* Mini chart */
|
||||
.mini-chart {
|
||||
padding: 20px 16px;
|
||||
background: #faf9f6;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
gap: 8px;
|
||||
padding-bottom: 36px;
|
||||
}
|
||||
.mini-bar {
|
||||
flex: 1;
|
||||
background: #2d2d2d;
|
||||
border-radius: 3px 3px 0 0;
|
||||
transform-origin: bottom;
|
||||
}
|
||||
|
||||
/* Mini social */
|
||||
.mini-social {
|
||||
background: #1a1a2e;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 16px;
|
||||
}
|
||||
.mini-tweet {
|
||||
background: rgba(255,255,255,0.06);
|
||||
border-radius: 12px;
|
||||
padding: 12px 14px;
|
||||
width: 100%;
|
||||
}
|
||||
.mini-tweet-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
.mini-avatar {
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(135deg, #74e1b9, #6adcff);
|
||||
}
|
||||
.mini-name { font-size: 11px; font-weight: 600; }
|
||||
.mini-handle { font-size: 10px; color: rgba(255,255,255,0.4); margin-left: 4px; }
|
||||
.mini-text { font-size: 10px; color: rgba(255,255,255,0.6); line-height: 1.4; }
|
||||
|
||||
/* Mini transition */
|
||||
.mini-transition { height: 100%; position: relative; }
|
||||
.mini-transition .half-a {
|
||||
position: absolute; inset: 0;
|
||||
background: linear-gradient(135deg, #667eea, #764ba2);
|
||||
}
|
||||
.mini-transition .half-b {
|
||||
position: absolute; inset: 0;
|
||||
background: linear-gradient(135deg, #f093fb, #f5576c);
|
||||
clip-path: circle(0% at 50% 50%);
|
||||
}
|
||||
|
||||
/* Mini kinetic */
|
||||
.mini-kinetic {
|
||||
background: #0a0a0f;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.mini-kinetic-text {
|
||||
font-size: 28px;
|
||||
font-weight: 900;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 4px;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
/* Mini app */
|
||||
.mini-app {
|
||||
background: linear-gradient(135deg, #e8e4d9, #d4cfbf);
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 6px;
|
||||
}
|
||||
.mini-phone {
|
||||
width: 36px;
|
||||
height: 64px;
|
||||
background: #1a1a2e;
|
||||
border-radius: 6px;
|
||||
border: 1px solid rgba(255,255,255,0.1);
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
|
||||
/* ── Tagline ── */
|
||||
.tagline {
|
||||
position: absolute;
|
||||
bottom: 24px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
text-align: center;
|
||||
font-size: 18px;
|
||||
color: rgba(255,255,255,0.25);
|
||||
letter-spacing: 3px;
|
||||
text-transform: uppercase;
|
||||
opacity: 0;
|
||||
}
|
||||
.tagline span { color: #74e1b9; font-weight: 600; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root" data-composition-id="readme-demo" data-start="0" data-duration="5.5" data-width="1920" data-height="1080">
|
||||
|
||||
<div class="bg-grid" id="bg-grid"></div>
|
||||
<div class="accent-orb orb-1" id="orb-1"></div>
|
||||
<div class="accent-orb orb-2" id="orb-2"></div>
|
||||
|
||||
<!-- Code panel -->
|
||||
<div class="code-panel" id="code-panel">
|
||||
<div class="code-header">
|
||||
<div class="code-dot"></div>
|
||||
<div class="code-dot"></div>
|
||||
<div class="code-dot"></div>
|
||||
<span class="code-filename">index.html</span>
|
||||
</div>
|
||||
<div class="code-content">
|
||||
<span class="code-line" id="cl-1"><span class="c-tag"><div</span> <span class="c-attr">data-composition-id</span>=<span class="c-val">"hero"</span><span class="c-tag">></span></span>
|
||||
<span class="code-line" id="cl-2"></span>
|
||||
<span class="code-line" id="cl-3"> <span class="c-tag"><h1</span> <span class="c-attr">class</span>=<span class="c-val">"clip"</span></span>
|
||||
<span class="code-line" id="cl-4"> <span class="c-attr">data-start</span>=<span class="c-val">"0"</span> <span class="c-attr">data-duration</span>=<span class="c-val">"5"</span><span class="c-tag">></span></span>
|
||||
<span class="code-line" id="cl-5"> Launch Day</span>
|
||||
<span class="code-line" id="cl-6"> <span class="c-tag"></h1></span></span>
|
||||
<span class="code-line" id="cl-7"></span>
|
||||
<span class="code-line" id="cl-8"> <span class="c-tag"><p</span> <span class="c-attr">class</span>=<span class="c-val">"clip"</span></span>
|
||||
<span class="code-line" id="cl-9"> <span class="c-attr">data-start</span>=<span class="c-val">"0.8"</span> <span class="c-attr">data-duration</span>=<span class="c-val">"4"</span><span class="c-tag">></span></span>
|
||||
<span class="code-line" id="cl-10"> The future of video</span>
|
||||
<span class="code-line" id="cl-11"> <span class="c-tag"></p></span></span>
|
||||
<span class="code-line" id="cl-12"></span>
|
||||
<span class="code-line" id="cl-13"> <span class="c-cmt"><!-- GSAP handles animation --></span></span>
|
||||
<span class="code-line" id="cl-14"> <span class="c-tag"><script></span></span>
|
||||
<span class="code-line" id="cl-15"> tl.<span class="c-attr">from</span>(<span class="c-str">"h1"</span>, {<span class="c-attr">y</span>: <span class="c-val">-60</span>, <span class="c-attr">opacity</span>: <span class="c-val">0</span>})</span>
|
||||
<span class="code-line" id="cl-16"> tl.<span class="c-attr">from</span>(<span class="c-str">"p"</span>, {<span class="c-attr">y</span>: <span class="c-val">40</span>, <span class="c-attr">opacity</span>: <span class="c-val">0</span>})</span>
|
||||
<span class="code-line" id="cl-17"> <span class="c-tag"></script></span></span>
|
||||
<span class="code-line" id="cl-18"><span class="c-tag"></div></span></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Arrow -->
|
||||
<div class="arrow" id="arrow">
|
||||
<svg viewBox="0 0 44 44" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M8 22h28M28 14l8 8-8 8" stroke="#74e1b9" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<!-- Output panel -->
|
||||
<div class="output-panel" id="output-panel">
|
||||
<span class="output-label">rendered output</span>
|
||||
<div class="preview-stage">
|
||||
<div class="preview-content">
|
||||
<div class="preview-title" id="preview-title">
|
||||
<span class="line-1">Launch Day</span>
|
||||
<span class="line-2">is here.</span>
|
||||
</div>
|
||||
<p class="preview-subtitle" id="preview-subtitle">The future of video</p>
|
||||
<div class="preview-btn" id="preview-btn">Get started</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Showcase strip -->
|
||||
<div class="showcase-strip" id="showcase-strip">
|
||||
<div class="showcase-card" id="sc-1">
|
||||
<div class="mini-chart">
|
||||
<div class="mini-bar" style="height: 35%"></div>
|
||||
<div class="mini-bar" style="height: 60%"></div>
|
||||
<div class="mini-bar" style="height: 85%"></div>
|
||||
<div class="mini-bar" style="height: 50%"></div>
|
||||
<div class="mini-bar" style="height: 95%"></div>
|
||||
<div class="mini-bar" style="height: 72%"></div>
|
||||
</div>
|
||||
<div class="card-label">Data Charts</div>
|
||||
</div>
|
||||
|
||||
<div class="showcase-card" id="sc-2">
|
||||
<div class="mini-social">
|
||||
<div class="mini-tweet">
|
||||
<div class="mini-tweet-header">
|
||||
<div class="mini-avatar"></div>
|
||||
<span class="mini-name">HyperFrames</span>
|
||||
<span class="mini-handle">@hyperframes</span>
|
||||
</div>
|
||||
<div class="mini-text">Write HTML. Render video.</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-label">Social Overlays</div>
|
||||
</div>
|
||||
|
||||
<div class="showcase-card" id="sc-3">
|
||||
<div class="mini-transition">
|
||||
<div class="half-a"></div>
|
||||
<div class="half-b" id="transition-b"></div>
|
||||
</div>
|
||||
<div class="card-label">Shader Transitions</div>
|
||||
</div>
|
||||
|
||||
<div class="showcase-card" id="sc-4">
|
||||
<div class="mini-kinetic">
|
||||
<span class="mini-kinetic-text" id="kinetic-text">BOLD</span>
|
||||
</div>
|
||||
<div class="card-label">Kinetic Type</div>
|
||||
</div>
|
||||
|
||||
<div class="showcase-card" id="sc-5">
|
||||
<div class="mini-app">
|
||||
<div class="mini-phone" id="phone-1"></div>
|
||||
<div class="mini-phone" id="phone-2" style="height: 72px; width: 40px"></div>
|
||||
<div class="mini-phone" id="phone-3"></div>
|
||||
</div>
|
||||
<div class="card-label">App Showcases</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tagline -->
|
||||
<div class="tagline" id="tagline">
|
||||
Write HTML · Render Video · <span>Built for agents</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
window.__timelines = window.__timelines || {};
|
||||
const tl = gsap.timeline({ paused: true });
|
||||
|
||||
// Background
|
||||
tl.to("#bg-grid", { opacity: 1, duration: 0.8 }, 0);
|
||||
tl.to("#orb-1", { opacity: 1, duration: 1.2 }, 0.2);
|
||||
tl.to("#orb-2", { opacity: 1, duration: 1.2 }, 0.4);
|
||||
|
||||
// Code panel slides in
|
||||
tl.fromTo("#code-panel",
|
||||
{ opacity: 0, x: -40 },
|
||||
{ opacity: 1, x: 0, duration: 0.6, ease: "power2.out" }, 0.3);
|
||||
|
||||
// Code lines type in
|
||||
const lines = [];
|
||||
for (let i = 1; i <= 18; i++) lines.push("#cl-" + i);
|
||||
tl.to(lines.join(","), {
|
||||
opacity: 1, duration: 0.06, stagger: 0.055, ease: "none"
|
||||
}, 0.5);
|
||||
|
||||
// Arrow
|
||||
tl.to("#arrow", { opacity: 1, duration: 0.3 }, 1.5);
|
||||
|
||||
// Output panel slides in
|
||||
tl.fromTo("#output-panel",
|
||||
{ opacity: 0, x: 40 },
|
||||
{ opacity: 1, x: 0, duration: 0.6, ease: "power2.out" }, 1.3);
|
||||
|
||||
// Preview content animates — mirrors what the code would render
|
||||
tl.fromTo("#preview-title",
|
||||
{ opacity: 0, y: -60 },
|
||||
{ opacity: 1, y: 0, duration: 0.7, ease: "power3.out" }, 1.7);
|
||||
tl.fromTo("#preview-subtitle",
|
||||
{ opacity: 0, y: 40 },
|
||||
{ opacity: 1, y: 0, duration: 0.5, ease: "power2.out" }, 2.1);
|
||||
tl.fromTo("#preview-btn",
|
||||
{ opacity: 0, scale: 0.8 },
|
||||
{ opacity: 1, scale: 1, duration: 0.4, ease: "back.out(2)" }, 2.4);
|
||||
|
||||
// Showcase strip
|
||||
tl.to("#showcase-strip", { opacity: 1, duration: 0.4 }, 3.0);
|
||||
tl.to(["#sc-1","#sc-2","#sc-3","#sc-4","#sc-5"].join(","), {
|
||||
opacity: 1, y: 0, duration: 0.4, stagger: 0.1, ease: "power2.out"
|
||||
}, 3.2);
|
||||
|
||||
// Mini card animations
|
||||
tl.fromTo("#sc-1 .mini-bar",
|
||||
{ scaleY: 0 },
|
||||
{ scaleY: 1, duration: 0.5, stagger: 0.05, ease: "power2.out" }, 3.4);
|
||||
tl.to("#transition-b",
|
||||
{ clipPath: "circle(75% at 50% 50%)", duration: 1.0, ease: "power2.inOut" }, 3.5);
|
||||
tl.fromTo("#kinetic-text",
|
||||
{ opacity: 0, scale: 3 },
|
||||
{ opacity: 1, scale: 1, duration: 0.3, ease: "power4.out" }, 3.6);
|
||||
tl.to(["#phone-1","#phone-2","#phone-3"].join(","), {
|
||||
opacity: 1, y: 0, duration: 0.4, stagger: 0.08, ease: "power2.out"
|
||||
}, 3.5);
|
||||
|
||||
// Tagline
|
||||
tl.to("#tagline", { opacity: 1, duration: 0.6 }, 4.0);
|
||||
|
||||
// Hold
|
||||
tl.set({}, {}, 5.5);
|
||||
|
||||
window.__timelines["readme-demo"] = tl;
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.6 MiB |
Binary file not shown.
Reference in New Issue
Block a user