← back to Rentv Tour
Master Reel: curated hero montage + Steve HeyGen avatar circular PIP (driven by ElevenLabs VO)
5986d75490a24a5156e62a36e7300ea40c66454e · 2026-07-28 13:59:43 -0700 · Steve Abrams
Files touched
A generate-reel.mjsA videos/reel/AGENTS.mdA videos/reel/CLAUDE.mdA videos/reel/hyperframes.jsonA videos/reel/index.htmlA videos/reel/meta.jsonA videos/reel/package.json
Diff
commit 5986d75490a24a5156e62a36e7300ea40c66454e
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Tue Jul 28 13:59:43 2026 -0700
Master Reel: curated hero montage + Steve HeyGen avatar circular PIP (driven by ElevenLabs VO)
---
generate-reel.mjs | 83 ++++++++++++++++++++++++++++++++++++++
videos/reel/AGENTS.md | 95 ++++++++++++++++++++++++++++++++++++++++++++
videos/reel/CLAUDE.md | 95 ++++++++++++++++++++++++++++++++++++++++++++
videos/reel/hyperframes.json | 13 ++++++
videos/reel/index.html | 85 +++++++++++++++++++++++++++++++++++++++
videos/reel/meta.json | 5 +++
videos/reel/package.json | 11 +++++
7 files changed, 387 insertions(+)
diff --git a/generate-reel.mjs b/generate-reel.mjs
new file mode 100644
index 0000000..24aab2c
--- /dev/null
+++ b/generate-reel.mjs
@@ -0,0 +1,83 @@
+import fs from 'fs';
+const W = 1920, H = 1080;
+const esc = (s) => String(s).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
+
+// Curated hero montage — silent (the Steve-avatar PIP clip carries the voice).
+const SHOTS = [
+ ['01-home.png', 'Live CRE News', 'FRONT END'],
+ ['02-markets.png', 'Markets', 'FRONT END'],
+ ['03-deals.png', 'Deals', 'FRONT END'],
+ ['04-pulse.png', 'Market Pulse', 'FRONT END'],
+ ['05-review.png', 'The REview', 'FRONT END'],
+ ['06-backend.png', 'Admin Backend', 'BACKEND'],
+ ['07-desk.png', 'Broker & Owner Desk', 'BACKEND'],
+ ['08-audience.png', 'Audience & CRM', 'BACKEND'],
+ ['09-press.png', 'Video Library', 'BACKEND'],
+];
+
+const clips = [], tweens = [];
+let t = 0;
+const TITLE = 2.2, OUTRO = 2.7, SHOT = 2.35;
+
+// title
+clips.push(` <section id="title" class="clip card" data-start="0" data-duration="${TITLE}" data-track-index="1">
+ <div class="ci"><div class="tag" id="title-tag">RENTV.COM</div><h1 id="title-h">The unified platform</h1></div></section>`);
+tweens.push(`tl.from('#title-h',{y:34,autoAlpha:0,duration:0.6,ease:'power3.out'},0.15);`);
+tweens.push(`tl.from('#title-tag',{y:-16,autoAlpha:0,duration:0.5},0.05);`);
+t = TITLE;
+
+SHOTS.forEach((s, i) => {
+ const [file, label, tag] = s;
+ const st = t + i * SHOT;
+ const accent = tag === 'BACKEND' ? '#c8a15a' : '#0a6cff';
+ clips.push(` <div id="s${i}" class="clip shot" data-start="${st.toFixed(3)}" data-duration="${SHOT}" data-track-index="2"><img id="s${i}-img" class="simg" src="assets/${file}" alt="${esc(label)}"></div>`);
+ clips.push(` <div id="s${i}-l" class="clip label" data-start="${st.toFixed(3)}" data-duration="${SHOT}" data-track-index="3"><div id="s${i}-li" class="li"><span class="num" style="background:${accent}">${tag}</span><span class="txt">${esc(label)}</span></div></div>`);
+ tweens.push(`tl.from('#s${i}-img',{opacity:0,duration:0.3,ease:'power1.out'},${st.toFixed(3)});`);
+ tweens.push(`tl.fromTo('#s${i}-img',{scale:1.07},{scale:1.0,duration:${SHOT},ease:'none'},${st.toFixed(3)});`);
+ tweens.push(`tl.from('#s${i}-li',{y:22,autoAlpha:0,duration:0.35,ease:'power2.out'},${(st + 0.05).toFixed(3)});`);
+});
+t = TITLE + SHOTS.length * SHOT;
+
+clips.push(` <section id="outro" class="clip card" data-start="${t.toFixed(3)}" data-duration="${OUTRO}" data-track-index="1">
+ <div class="ci"><h1 id="outro-h">rentv.agentabrams.com</h1><p id="outro-p">One unified app · news + intelligence</p></div></section>`);
+tweens.push(`tl.from('#outro-h',{y:30,autoAlpha:0,duration:0.6,ease:'power3.out'},${t.toFixed(3)});`);
+tweens.push(`tl.from('#outro-p',{y:18,autoAlpha:0,duration:0.5},${(t + 0.25).toFixed(3)});`);
+const TOTAL = +(t + OUTRO).toFixed(2);
+
+const html = `<!doctype html>
+<html lang="en"><head>
+<meta charset="UTF-8" /><meta name="viewport" content="width=1920, height=1080" />
+<title>RENTV — Master Reel</title>
+<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
+<style>
+ body{margin:0;background:#070b10;font-family:system-ui,-apple-system,"Helvetica Neue",Arial,sans-serif}
+ #root{position:relative;width:${W}px;height:${H}px;overflow:hidden}
+ .clip{position:absolute;inset:0}
+ #bg{background:radial-gradient(120% 120% at 50% 0%,#0d1725 0%,#070b10 60%)}
+ .shot{overflow:hidden}
+ .simg{width:100%;height:100%;object-fit:cover;object-position:top center;display:block;will-change:transform,opacity}
+ .card{display:grid;place-items:center}
+ .ci{text-align:center;padding:0 120px}
+ .card .tag{font-size:22px;letter-spacing:.42em;font-weight:600;color:#57b0ff;margin-bottom:20px}
+ .card h1{margin:0;color:#f3f7fc;font-size:96px;font-weight:500;letter-spacing:-.01em}
+ .card p{margin:20px 0 0;color:#8ea3b8;font-size:30px;font-weight:300}
+ .label{left:56px;bottom:64px;right:auto;top:auto;width:auto;height:auto}
+ .li{display:flex;align-items:center;gap:14px}
+ .li .num{color:#fff;font-size:18px;font-weight:600;letter-spacing:.08em;padding:8px 13px;border-radius:8px}
+ .li .txt{color:#fff;font-size:30px;font-weight:500;background:rgba(9,15,24,.9);padding:8px 18px;border-radius:10px}
+</style></head>
+<body>
+ <div id="root" data-composition-id="main" data-start="0" data-width="${W}" data-height="${H}" data-duration="${TOTAL}" data-fps="30">
+ <div id="bg" class="clip" data-start="0" data-duration="${TOTAL}" data-track-index="0"></div>
+${clips.join('\n')}
+ </div>
+ <script>
+ window.__timelines = window.__timelines || {};
+ const tl = gsap.timeline({ paused: true });
+${tweens.map(x => ' ' + x).join('\n')}
+ window.__timelines['main'] = tl;
+ </script>
+</body></html>
+`;
+fs.writeFileSync('videos/reel/index.html', html);
+console.log(`reel: ${TOTAL}s, ${SHOTS.length} shots`);
diff --git a/videos/reel/AGENTS.md b/videos/reel/AGENTS.md
new file mode 100644
index 0000000..c4ff0ae
--- /dev/null
+++ b/videos/reel/AGENTS.md
@@ -0,0 +1,95 @@
+# HyperFrames Composition Project
+
+## Skills — USE THESE FIRST
+
+**Always invoke the relevant skill before writing or modifying compositions.** Skills encode framework-specific patterns (e.g., `window.__timelines` registration, `data-*` attribute semantics, shader-compatible CSS rules) that are NOT in generic web docs. Skipping them produces broken compositions.
+
+**Doing anything with HyperFrames?** Start at `/hyperframes` — it tells you what HyperFrames can do and which skill or workflow handles your intent (make a video, TTS / BGM, prep footage, author / animate, render, install blocks), confirms your brief up front (the intent layer), and routes every "make me a…" request (a video, a deck, a composition port) to the right workflow. Read it first, especially when there's no project context to orient you. The workflows it routes to:
+
+- `/product-launch-video` — any **website** URL or brief / script → a product launch / SaaS / promo video, or a site tour / showcase featuring the site's own captured visuals.
+- `/faceless-explainer` — arbitrary text (topic / article / notes), **no URL, no website capture** → 60-90s faceless explainer.
+- `/embedded-captions` — an existing talking-head video (MP4) → the same footage with captions / subtitles added (rail + embed, or pure-cinematic embed); the footage itself is untouched.
+- `/talking-head-recut` — an existing talking-head / interview / podcast video (MP4) → the same footage **packaged with designed graphic overlays** (kinetic titles, lower-thirds, data callouts, pull-quotes, side panels, pip) synced to the transcript; the clip plays unchanged underneath. (Plain captions/subtitles → `/embedded-captions`.)
+- `/pr-to-video` — a GitHub PR (URL / `owner/repo#N` / "this PR") → 30-90s code-change explainer (changelog / feature reveal / fix / refactor).
+- `/motion-graphics` — a short (typically under 10s) design-led **motion graphic**, motion-is-the-message, no narration: kinetic type, a stat / number count-up, a chart, a logo sting, a lower-third / overlay, or an animated tweet / headline / captured-page highlight; rendered to MP4 or a transparent overlay. Longer / narrated / custom → `/general-video`.
+- `/music-to-video` — a **music track** (audio file, or video to pull audio from) → beat-synced video (lyric / slideshow / kinetic promo). Music drives pacing; user-supplied images / videos are cut onto the same beat grid.
+- `/slideshow` — a **presentation / pitch deck / interactive deck** — discrete slides, fragment reveals, branching, hotspot navigation, presenter mode. Output is a navigable deck, not a rendered video.
+- `/general-video` — fallback for any other video (title card, longer brand / sizzle reel, multi-scene montage, static loop, custom composition) and the home of **companion mode** — co-create with the full HyperFrames toolbox; the original hyperframes authoring flow, any length.
+
+**Porting an existing composition?** `/remotion-to-hyperframes` translates a Remotion (React) composition into HyperFrames HTML — a source migration, separate from the creation workflows above.
+
+The domain skills (`/hyperframes-core`, `/hyperframes-animation`, `/hyperframes-keyframes`, `/hyperframes-creative`, `/hyperframes-cli`, `/media-use`, `/hyperframes-registry`, `/figma`) and the full capability map live inside `/hyperframes` — it is the single source of truth for which skill handles which intent.
+
+**Changing how real footage or images look or reveal?** Load `/media-use` and its media-treatment policy before editing, even when the request only says dark, flat, boring, retro, private, or “make the reveal cooler.” Use canonical media treatments and seek-safe motion; do not improvise equivalent CSS/SVG filters or overlays.
+
+> **Tailwind v4 projects** (`hyperframes init --tailwind`): see `/hyperframes-core` → `references/tailwind.md`.
+
+> **Skill missing or stale?** Run `npx hyperframes skills update <name>` to install/refresh
+> the specific skill you need (the `/hyperframes` router does this automatically before
+> entering a workflow), or bare `npx hyperframes skills update` to refresh the core set plus
+> everything already installed — neither pulls the full set. Restart the agent session so
+> newly installed skills load.
+
+## Commands
+
+```bash
+npm run dev # start the preview server (long-running — keep it alive in background)
+npm run check # lint + runtime + layout + motion + contrast (one command)
+npm run render # render to MP4
+npm run publish # publish and get a shareable link
+npx hyperframes lint --verbose # include info-level findings
+npx hyperframes lint --json # machine-readable output for CI
+npx hyperframes docs <topic> # reference docs in terminal
+```
+
+> **`npm run dev` is a long-running server, not a one-shot command.** It blocks until stopped.
+> In Claude Code, always run it with `run_in_background: true`. Never run it as a foreground
+> command — it will time out and the server will die, breaking the browser preview.
+
+> **Pinned CLI version.** These scripts pin an exact `hyperframes@X.Y.Z` so this project re-renders identically over time. Weeks later that pin lags fixes shipped since. To move up: `npx hyperframes@latest upgrade --project . --check` (shows the delta), then `npx hyperframes@latest upgrade --project .` to rewrite the pins. Always unpinned — the pinned script re-runs the old version against itself.
+
+## Documentation
+
+**For quick reference**, use the local CLI docs command (no network required):
+
+```bash
+npx hyperframes docs <topic>
+```
+
+Topics: `data-attributes`, `gsap`, `compositions`, `rendering`, `examples`, `troubleshooting`
+
+**For full documentation**, discover pages via the machine-readable index — do NOT guess URLs:
+
+```
+https://hyperframes.heygen.com/llms.txt
+```
+
+## 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)
+
+## Linting — ALWAYS RUN AFTER CHANGES
+
+After creating or editing any `.html` composition, **always** run the full check before considering the task complete:
+
+```bash
+npm run check
+```
+
+Fix all errors before presenting the result. Warnings should be reviewed before rendering.
+
+## 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 `<audio>` element for the audio track
+5. Sub-compositions use `data-composition-src="compositions/file.html"` to reference other HTML files
+6. Only deterministic logic — no `Date.now()`, no `Math.random()`, no network fetches
diff --git a/videos/reel/CLAUDE.md b/videos/reel/CLAUDE.md
new file mode 100644
index 0000000..c4ff0ae
--- /dev/null
+++ b/videos/reel/CLAUDE.md
@@ -0,0 +1,95 @@
+# HyperFrames Composition Project
+
+## Skills — USE THESE FIRST
+
+**Always invoke the relevant skill before writing or modifying compositions.** Skills encode framework-specific patterns (e.g., `window.__timelines` registration, `data-*` attribute semantics, shader-compatible CSS rules) that are NOT in generic web docs. Skipping them produces broken compositions.
+
+**Doing anything with HyperFrames?** Start at `/hyperframes` — it tells you what HyperFrames can do and which skill or workflow handles your intent (make a video, TTS / BGM, prep footage, author / animate, render, install blocks), confirms your brief up front (the intent layer), and routes every "make me a…" request (a video, a deck, a composition port) to the right workflow. Read it first, especially when there's no project context to orient you. The workflows it routes to:
+
+- `/product-launch-video` — any **website** URL or brief / script → a product launch / SaaS / promo video, or a site tour / showcase featuring the site's own captured visuals.
+- `/faceless-explainer` — arbitrary text (topic / article / notes), **no URL, no website capture** → 60-90s faceless explainer.
+- `/embedded-captions` — an existing talking-head video (MP4) → the same footage with captions / subtitles added (rail + embed, or pure-cinematic embed); the footage itself is untouched.
+- `/talking-head-recut` — an existing talking-head / interview / podcast video (MP4) → the same footage **packaged with designed graphic overlays** (kinetic titles, lower-thirds, data callouts, pull-quotes, side panels, pip) synced to the transcript; the clip plays unchanged underneath. (Plain captions/subtitles → `/embedded-captions`.)
+- `/pr-to-video` — a GitHub PR (URL / `owner/repo#N` / "this PR") → 30-90s code-change explainer (changelog / feature reveal / fix / refactor).
+- `/motion-graphics` — a short (typically under 10s) design-led **motion graphic**, motion-is-the-message, no narration: kinetic type, a stat / number count-up, a chart, a logo sting, a lower-third / overlay, or an animated tweet / headline / captured-page highlight; rendered to MP4 or a transparent overlay. Longer / narrated / custom → `/general-video`.
+- `/music-to-video` — a **music track** (audio file, or video to pull audio from) → beat-synced video (lyric / slideshow / kinetic promo). Music drives pacing; user-supplied images / videos are cut onto the same beat grid.
+- `/slideshow` — a **presentation / pitch deck / interactive deck** — discrete slides, fragment reveals, branching, hotspot navigation, presenter mode. Output is a navigable deck, not a rendered video.
+- `/general-video` — fallback for any other video (title card, longer brand / sizzle reel, multi-scene montage, static loop, custom composition) and the home of **companion mode** — co-create with the full HyperFrames toolbox; the original hyperframes authoring flow, any length.
+
+**Porting an existing composition?** `/remotion-to-hyperframes` translates a Remotion (React) composition into HyperFrames HTML — a source migration, separate from the creation workflows above.
+
+The domain skills (`/hyperframes-core`, `/hyperframes-animation`, `/hyperframes-keyframes`, `/hyperframes-creative`, `/hyperframes-cli`, `/media-use`, `/hyperframes-registry`, `/figma`) and the full capability map live inside `/hyperframes` — it is the single source of truth for which skill handles which intent.
+
+**Changing how real footage or images look or reveal?** Load `/media-use` and its media-treatment policy before editing, even when the request only says dark, flat, boring, retro, private, or “make the reveal cooler.” Use canonical media treatments and seek-safe motion; do not improvise equivalent CSS/SVG filters or overlays.
+
+> **Tailwind v4 projects** (`hyperframes init --tailwind`): see `/hyperframes-core` → `references/tailwind.md`.
+
+> **Skill missing or stale?** Run `npx hyperframes skills update <name>` to install/refresh
+> the specific skill you need (the `/hyperframes` router does this automatically before
+> entering a workflow), or bare `npx hyperframes skills update` to refresh the core set plus
+> everything already installed — neither pulls the full set. Restart the agent session so
+> newly installed skills load.
+
+## Commands
+
+```bash
+npm run dev # start the preview server (long-running — keep it alive in background)
+npm run check # lint + runtime + layout + motion + contrast (one command)
+npm run render # render to MP4
+npm run publish # publish and get a shareable link
+npx hyperframes lint --verbose # include info-level findings
+npx hyperframes lint --json # machine-readable output for CI
+npx hyperframes docs <topic> # reference docs in terminal
+```
+
+> **`npm run dev` is a long-running server, not a one-shot command.** It blocks until stopped.
+> In Claude Code, always run it with `run_in_background: true`. Never run it as a foreground
+> command — it will time out and the server will die, breaking the browser preview.
+
+> **Pinned CLI version.** These scripts pin an exact `hyperframes@X.Y.Z` so this project re-renders identically over time. Weeks later that pin lags fixes shipped since. To move up: `npx hyperframes@latest upgrade --project . --check` (shows the delta), then `npx hyperframes@latest upgrade --project .` to rewrite the pins. Always unpinned — the pinned script re-runs the old version against itself.
+
+## Documentation
+
+**For quick reference**, use the local CLI docs command (no network required):
+
+```bash
+npx hyperframes docs <topic>
+```
+
+Topics: `data-attributes`, `gsap`, `compositions`, `rendering`, `examples`, `troubleshooting`
+
+**For full documentation**, discover pages via the machine-readable index — do NOT guess URLs:
+
+```
+https://hyperframes.heygen.com/llms.txt
+```
+
+## 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)
+
+## Linting — ALWAYS RUN AFTER CHANGES
+
+After creating or editing any `.html` composition, **always** run the full check before considering the task complete:
+
+```bash
+npm run check
+```
+
+Fix all errors before presenting the result. Warnings should be reviewed before rendering.
+
+## 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 `<audio>` element for the audio track
+5. Sub-compositions use `data-composition-src="compositions/file.html"` to reference other HTML files
+6. Only deterministic logic — no `Date.now()`, no `Math.random()`, no network fetches
diff --git a/videos/reel/hyperframes.json b/videos/reel/hyperframes.json
new file mode 100644
index 0000000..ec2e3c2
--- /dev/null
+++ b/videos/reel/hyperframes.json
@@ -0,0 +1,13 @@
+{
+ "$schema": "https://hyperframes.heygen.com/schema/hyperframes.json",
+ "registry": "https://raw.githubusercontent.com/heygen-com/hyperframes/main/registry",
+ "paths": {
+ "blocks": "compositions",
+ "components": "compositions/components",
+ "assets": "assets"
+ },
+ "media": {
+ "autoProxy": true
+ },
+ "authoringSkill": "product-launch-video"
+}
diff --git a/videos/reel/index.html b/videos/reel/index.html
new file mode 100644
index 0000000..ae2b791
--- /dev/null
+++ b/videos/reel/index.html
@@ -0,0 +1,85 @@
+<!doctype html>
+<html lang="en"><head>
+<meta charset="UTF-8" /><meta name="viewport" content="width=1920, height=1080" />
+<title>RENTV — Master Reel</title>
+<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
+<style>
+ body{margin:0;background:#070b10;font-family:system-ui,-apple-system,"Helvetica Neue",Arial,sans-serif}
+ #root{position:relative;width:1920px;height:1080px;overflow:hidden}
+ .clip{position:absolute;inset:0}
+ #bg{background:radial-gradient(120% 120% at 50% 0%,#0d1725 0%,#070b10 60%)}
+ .shot{overflow:hidden}
+ .simg{width:100%;height:100%;object-fit:cover;object-position:top center;display:block;will-change:transform,opacity}
+ .card{display:grid;place-items:center}
+ .ci{text-align:center;padding:0 120px}
+ .card .tag{font-size:22px;letter-spacing:.42em;font-weight:600;color:#57b0ff;margin-bottom:20px}
+ .card h1{margin:0;color:#f3f7fc;font-size:96px;font-weight:500;letter-spacing:-.01em}
+ .card p{margin:20px 0 0;color:#8ea3b8;font-size:30px;font-weight:300}
+ .label{left:56px;bottom:64px;right:auto;top:auto;width:auto;height:auto}
+ .li{display:flex;align-items:center;gap:14px}
+ .li .num{color:#fff;font-size:18px;font-weight:600;letter-spacing:.08em;padding:8px 13px;border-radius:8px}
+ .li .txt{color:#fff;font-size:30px;font-weight:500;background:rgba(9,15,24,.9);padding:8px 18px;border-radius:10px}
+</style></head>
+<body>
+ <div id="root" data-composition-id="main" data-start="0" data-width="1920" data-height="1080" data-duration="26.05" data-fps="30">
+ <div id="bg" class="clip" data-start="0" data-duration="26.05" data-track-index="0"></div>
+ <section id="title" class="clip card" data-start="0" data-duration="2.2" data-track-index="1">
+ <div class="ci"><div class="tag" id="title-tag">RENTV.COM</div><h1 id="title-h">The unified platform</h1></div></section>
+ <div id="s0" class="clip shot" data-start="2.200" data-duration="2.35" data-track-index="2"><img id="s0-img" class="simg" src="assets/01-home.png" alt="Live CRE News"></div>
+ <div id="s0-l" class="clip label" data-start="2.200" data-duration="2.35" data-track-index="3"><div id="s0-li" class="li"><span class="num" style="background:#0a6cff">FRONT END</span><span class="txt">Live CRE News</span></div></div>
+ <div id="s1" class="clip shot" data-start="4.550" data-duration="2.35" data-track-index="2"><img id="s1-img" class="simg" src="assets/02-markets.png" alt="Markets"></div>
+ <div id="s1-l" class="clip label" data-start="4.550" data-duration="2.35" data-track-index="3"><div id="s1-li" class="li"><span class="num" style="background:#0a6cff">FRONT END</span><span class="txt">Markets</span></div></div>
+ <div id="s2" class="clip shot" data-start="6.900" data-duration="2.35" data-track-index="2"><img id="s2-img" class="simg" src="assets/03-deals.png" alt="Deals"></div>
+ <div id="s2-l" class="clip label" data-start="6.900" data-duration="2.35" data-track-index="3"><div id="s2-li" class="li"><span class="num" style="background:#0a6cff">FRONT END</span><span class="txt">Deals</span></div></div>
+ <div id="s3" class="clip shot" data-start="9.250" data-duration="2.35" data-track-index="2"><img id="s3-img" class="simg" src="assets/04-pulse.png" alt="Market Pulse"></div>
+ <div id="s3-l" class="clip label" data-start="9.250" data-duration="2.35" data-track-index="3"><div id="s3-li" class="li"><span class="num" style="background:#0a6cff">FRONT END</span><span class="txt">Market Pulse</span></div></div>
+ <div id="s4" class="clip shot" data-start="11.600" data-duration="2.35" data-track-index="2"><img id="s4-img" class="simg" src="assets/05-review.png" alt="The REview"></div>
+ <div id="s4-l" class="clip label" data-start="11.600" data-duration="2.35" data-track-index="3"><div id="s4-li" class="li"><span class="num" style="background:#0a6cff">FRONT END</span><span class="txt">The REview</span></div></div>
+ <div id="s5" class="clip shot" data-start="13.950" data-duration="2.35" data-track-index="2"><img id="s5-img" class="simg" src="assets/06-backend.png" alt="Admin Backend"></div>
+ <div id="s5-l" class="clip label" data-start="13.950" data-duration="2.35" data-track-index="3"><div id="s5-li" class="li"><span class="num" style="background:#c8a15a">BACKEND</span><span class="txt">Admin Backend</span></div></div>
+ <div id="s6" class="clip shot" data-start="16.300" data-duration="2.35" data-track-index="2"><img id="s6-img" class="simg" src="assets/07-desk.png" alt="Broker & Owner Desk"></div>
+ <div id="s6-l" class="clip label" data-start="16.300" data-duration="2.35" data-track-index="3"><div id="s6-li" class="li"><span class="num" style="background:#c8a15a">BACKEND</span><span class="txt">Broker & Owner Desk</span></div></div>
+ <div id="s7" class="clip shot" data-start="18.650" data-duration="2.35" data-track-index="2"><img id="s7-img" class="simg" src="assets/08-audience.png" alt="Audience & CRM"></div>
+ <div id="s7-l" class="clip label" data-start="18.650" data-duration="2.35" data-track-index="3"><div id="s7-li" class="li"><span class="num" style="background:#c8a15a">BACKEND</span><span class="txt">Audience & CRM</span></div></div>
+ <div id="s8" class="clip shot" data-start="21.000" data-duration="2.35" data-track-index="2"><img id="s8-img" class="simg" src="assets/09-press.png" alt="Video Library"></div>
+ <div id="s8-l" class="clip label" data-start="21.000" data-duration="2.35" data-track-index="3"><div id="s8-li" class="li"><span class="num" style="background:#c8a15a">BACKEND</span><span class="txt">Video Library</span></div></div>
+ <section id="outro" class="clip card" data-start="23.350" data-duration="2.7" data-track-index="1">
+ <div class="ci"><h1 id="outro-h">rentv.agentabrams.com</h1><p id="outro-p">One unified app · news + intelligence</p></div></section>
+ </div>
+ <script>
+ window.__timelines = window.__timelines || {};
+ const tl = gsap.timeline({ paused: true });
+ tl.from('#title-h',{y:34,autoAlpha:0,duration:0.6,ease:'power3.out'},0.15);
+ tl.from('#title-tag',{y:-16,autoAlpha:0,duration:0.5},0.05);
+ tl.from('#s0-img',{opacity:0,duration:0.3,ease:'power1.out'},2.200);
+ tl.fromTo('#s0-img',{scale:1.07},{scale:1.0,duration:2.35,ease:'none'},2.200);
+ tl.from('#s0-li',{y:22,autoAlpha:0,duration:0.35,ease:'power2.out'},2.250);
+ tl.from('#s1-img',{opacity:0,duration:0.3,ease:'power1.out'},4.550);
+ tl.fromTo('#s1-img',{scale:1.07},{scale:1.0,duration:2.35,ease:'none'},4.550);
+ tl.from('#s1-li',{y:22,autoAlpha:0,duration:0.35,ease:'power2.out'},4.600);
+ tl.from('#s2-img',{opacity:0,duration:0.3,ease:'power1.out'},6.900);
+ tl.fromTo('#s2-img',{scale:1.07},{scale:1.0,duration:2.35,ease:'none'},6.900);
+ tl.from('#s2-li',{y:22,autoAlpha:0,duration:0.35,ease:'power2.out'},6.950);
+ tl.from('#s3-img',{opacity:0,duration:0.3,ease:'power1.out'},9.250);
+ tl.fromTo('#s3-img',{scale:1.07},{scale:1.0,duration:2.35,ease:'none'},9.250);
+ tl.from('#s3-li',{y:22,autoAlpha:0,duration:0.35,ease:'power2.out'},9.300);
+ tl.from('#s4-img',{opacity:0,duration:0.3,ease:'power1.out'},11.600);
+ tl.fromTo('#s4-img',{scale:1.07},{scale:1.0,duration:2.35,ease:'none'},11.600);
+ tl.from('#s4-li',{y:22,autoAlpha:0,duration:0.35,ease:'power2.out'},11.650);
+ tl.from('#s5-img',{opacity:0,duration:0.3,ease:'power1.out'},13.950);
+ tl.fromTo('#s5-img',{scale:1.07},{scale:1.0,duration:2.35,ease:'none'},13.950);
+ tl.from('#s5-li',{y:22,autoAlpha:0,duration:0.35,ease:'power2.out'},14.000);
+ tl.from('#s6-img',{opacity:0,duration:0.3,ease:'power1.out'},16.300);
+ tl.fromTo('#s6-img',{scale:1.07},{scale:1.0,duration:2.35,ease:'none'},16.300);
+ tl.from('#s6-li',{y:22,autoAlpha:0,duration:0.35,ease:'power2.out'},16.350);
+ tl.from('#s7-img',{opacity:0,duration:0.3,ease:'power1.out'},18.650);
+ tl.fromTo('#s7-img',{scale:1.07},{scale:1.0,duration:2.35,ease:'none'},18.650);
+ tl.from('#s7-li',{y:22,autoAlpha:0,duration:0.35,ease:'power2.out'},18.700);
+ tl.from('#s8-img',{opacity:0,duration:0.3,ease:'power1.out'},21.000);
+ tl.fromTo('#s8-img',{scale:1.07},{scale:1.0,duration:2.35,ease:'none'},21.000);
+ tl.from('#s8-li',{y:22,autoAlpha:0,duration:0.35,ease:'power2.out'},21.050);
+ tl.from('#outro-h',{y:30,autoAlpha:0,duration:0.6,ease:'power3.out'},23.350);
+ tl.from('#outro-p',{y:18,autoAlpha:0,duration:0.5},23.600);
+ window.__timelines['main'] = tl;
+ </script>
+</body></html>
diff --git a/videos/reel/meta.json b/videos/reel/meta.json
new file mode 100644
index 0000000..a13d13a
--- /dev/null
+++ b/videos/reel/meta.json
@@ -0,0 +1,5 @@
+{
+ "id": "reel",
+ "name": "reel",
+ "createdAt": "2026-07-28T20:57:46.322Z"
+}
\ No newline at end of file
diff --git a/videos/reel/package.json b/videos/reel/package.json
new file mode 100644
index 0000000..6961a35
--- /dev/null
+++ b/videos/reel/package.json
@@ -0,0 +1,11 @@
+{
+ "name": "reel",
+ "private": true,
+ "type": "module",
+ "scripts": {
+ "dev": "npx --yes hyperframes@0.7.78 preview",
+ "check": "npx --yes hyperframes@0.7.78 check",
+ "render": "npx --yes hyperframes@0.7.78 render",
+ "publish": "npx --yes hyperframes@0.7.78 publish"
+ }
+}
← ffff638 HeyGen: create Steve digital-twin avatar (photo-based) + AVA
·
back to Rentv Tour
·
Component video batch (18, Steve voice) + real bearded-Steve 1a67a3b →