The HyperFrames templates behind every video in v3. Placeholders in double underscores are filled per video: duration, headline, scenes and timing.
End card (CTA, logo, phone)
<!doctype html>
<html lang="en" data-resolution="portrait">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=1080, height=1920" />
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
<style>
@font-face { font-family: "Bebas"; src: url("assets/BebasNeue.ttf"); }
@font-face { font-family: "Oswald"; src: url("assets/Oswald.ttf"); font-weight: 200 700; }
:root { --lime: #7dc242; --ink: #0b0d0a; --white: #ffffff; --yellow: #f5d31c; }
* { margin: 0; padding: 0; box-sizing: border-box; }
html, body { width: 1080px; height: 1920px; overflow: hidden; background: var(--ink); }
#root { position: relative; width: 100%; height: 100%; overflow: hidden; font-family: "Oswald", sans-serif; color: var(--white); }
#bg { position: absolute; inset: 0; background: url("assets/bg.png") center/cover; filter: blur(6px) brightness(0.35) saturate(1.2); transform: scale(1.1); }
#shade { position: absolute; inset: 0; background: linear-gradient(180deg, rgba(11,13,10,0.55) 0%, rgba(11,13,10,0.2) 35%, rgba(11,13,10,0.9) 70%, var(--ink) 100%); }
#glow { position: absolute; left: 50%; top: 820px; width: 900px; height: 900px; margin-left: -450px; margin-top: -450px; border-radius: 50%; background: radial-gradient(circle, rgba(125,194,66,0.35) 0%, rgba(125,194,66,0) 65%); }
#logo { position: absolute; top: 150px; left: 50%; transform: translateX(-50%); border: 8px solid var(--lime); padding: 18px 46px 22px; text-align: center; background: rgba(11,13,10,0.85); }
#logo .word { font-family: "Bebas"; font-size: 150px; line-height: 0.9; letter-spacing: 2px; white-space: nowrap; }
#logo .word .oxy { color: var(--lime); }
#logo .word sup { font-size: 34px; vertical-align: top; position: relative; top: 12px; }
#logo .tag { font-family: "Bebas"; font-size: 44px; letter-spacing: 3px; margin-top: 4px; white-space: nowrap; }
#bottle { position: absolute; top: 450px; left: 190px; width: 700px; height: 700px; background: url("assets/bottle.png") center / contain no-repeat; }
#floor { position: absolute; top: 1090px; left: 290px; width: 500px; height: 60px; border-radius: 50%; background: radial-gradient(ellipse at center, rgba(0,0,0,0.65) 0%, rgba(0,0,0,0) 70%); }
#headline { position: absolute; top: 1180px; left: 60px; right: 60px; text-align: center; font-family: "Bebas"; font-size: 116px; line-height: 0.95; letter-spacing: 1px; }
#headline .hl { color: var(--lime); }
#cta { position: absolute; top: 1420px; left: 50%; transform: translateX(-50%); background: var(--lime); color: var(--ink); font-family: "Bebas"; font-size: 84px; letter-spacing: 2px; padding: 18px 64px 10px; border-radius: 14px; white-space: nowrap; box-shadow: 0 12px 40px rgba(125,194,66,0.45); }
#url { position: absolute; top: 1580px; left: 0; right: 0; text-align: center; font-family: "Bebas"; font-size: 72px; letter-spacing: 3px; }
#phone { position: absolute; top: 1670px; left: 0; right: 0; text-align: center; font-size: 56px; font-weight: 600; letter-spacing: 1px; color: var(--lime); }
#phone .ic { display: inline-block; width: 48px; height: 48px; vertical-align: -6px; margin-right: 14px; }
#safe { position: absolute; top: 1790px; left: 0; right: 0; text-align: center; font-size: 30px; font-weight: 400; letter-spacing: 4px; text-transform: uppercase; color: rgba(255,255,255,0.75); }
#bar { position: absolute; left: 0; right: 0; bottom: 0; height: 14px; background: var(--lime); transform-origin: left center; }
</style>
</head>
<body>
<div id="root" data-composition-id="main" data-start="0" data-duration="__DUR__" data-width="1080" data-height="1920">
<div id="bg" class="clip" data-start="0" data-duration="__DUR__"></div>
<div id="shade" class="clip" data-start="0" data-duration="__DUR__"></div>
<div id="glow" class="clip" data-start="0" data-duration="__DUR__"></div>
<div id="logo" class="clip" data-start="0" data-duration="__DUR__">
<div class="word"><span class="oxy">OXY</span>GREEN<sup>®</sup></div>
<div class="tag">TURF CLEANER & DEODORIZER</div>
</div>
<div id="floor" class="clip" data-start="0" data-duration="__DUR__"></div>
<div id="bottle" class="clip" data-start="0" data-duration="__DUR__"></div>
<div id="headline" class="clip" data-start="0" data-duration="__DUR__">__HEADLINE__</div>
<div id="cta" class="clip" data-start="0" data-duration="__DUR__">SHOP NOW →</div>
<div id="url" class="clip" data-start="0" data-duration="__DUR__">OXYGREENUSA.COM</div>
<div id="phone" class="clip" data-start="0" data-duration="__DUR__">
<svg class="ic" viewBox="0 0 24 24" fill="#7dc242"><path d="M6.6 10.8a15.2 15.2 0 0 0 6.6 6.6l2.2-2.2a1 1 0 0 1 1-.25 11.4 11.4 0 0 0 3.6.57 1 1 0 0 1 1 1V20a1 1 0 0 1-1 1A17 17 0 0 1 3 4a1 1 0 0 1 1-1h3.5a1 1 0 0 1 1 1c0 1.25.2 2.45.57 3.57a1 1 0 0 1-.25 1z"/></svg>(800) 625-8170
</div>
<div id="safe" class="clip" data-start="0" data-duration="__DUR__">Safe around pets, plants & children</div>
<div id="bar" class="clip" data-start="0" data-duration="__DUR__"></div>
</div>
<script>
const tl = gsap.timeline({ paused: true });
tl.fromTo("#glow", { opacity: 0, scale: 0.6 }, { opacity: 1, scale: 1, duration: 1.2, ease: "power2.out" }, 0);
tl.fromTo("#logo", { opacity: 0, y: -60, scale: 0.9 }, { opacity: 1, y: 0, scale: 1, duration: 0.6, ease: "back.out(1.6)" }, 0.1);
tl.fromTo("#bottle", { opacity: 0, y: 120 }, { opacity: 1, y: 0, duration: 0.7, ease: "power3.out" }, 0.3);
tl.fromTo("#floor", { opacity: 0 }, { opacity: 1, duration: 0.7 }, 0.3);
tl.fromTo("#headline", { opacity: 0, y: 50 }, { opacity: 1, y: 0, duration: 0.5, ease: "power3.out" }, 0.7);
tl.fromTo("#cta", { opacity: 0, scale: 0.6 }, { opacity: 1, scale: 1, duration: 0.5, ease: "back.out(2)" }, 1.1);
tl.to("#cta", { scale: 1.06, duration: 0.45, ease: "sine.inOut", yoyo: true, repeat: Math.floor((__DUR__ - 1.8) / 0.45) - 1 }, 1.8);
tl.fromTo("#url", { opacity: 0, y: 30 }, { opacity: 1, y: 0, duration: 0.4, ease: "power2.out" }, 1.35);
tl.fromTo("#phone", { opacity: 0, y: 30 }, { opacity: 1, y: 0, duration: 0.4, ease: "power2.out" }, 1.5);
tl.fromTo("#safe", { opacity: 0 }, { opacity: 1, duration: 0.5 }, 1.7);
tl.fromTo("#bar", { scaleX: 0 }, { scaleX: 1, duration: __DUR__, ease: "none" }, 0);
window.__timelines["main"] = tl;
tl.seek(0);
</script>
</body>
</html>
Talking cards (scenes, logo, phone, text cards)
<!doctype html>
<html lang="en" data-resolution="portrait">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=1080, height=1920" />
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
<style>
@font-face { font-family: "Bebas"; src: url("assets/BebasNeue.ttf"); }
@font-face { font-family: "Oswald"; src: url("assets/Oswald.ttf"); font-weight: 200 700; }
:root { --lime: #7dc242; --ink: #0b0d0a; --white: #ffffff; }
* { margin: 0; padding: 0; box-sizing: border-box; }
html, body { width: 1080px; height: 1920px; overflow: hidden; background: var(--ink); }
#root { position: relative; width: 100%; height: 100%; overflow: hidden; font-family: "Oswald", sans-serif; color: var(--white); }
.scene { position: absolute; inset: 0; overflow: hidden; }
.scene .img { position: absolute; inset: 0; background-size: cover; background-position: center; }
.scene .shade { position: absolute; inset: 0; background: linear-gradient(180deg, rgba(11,13,10,0.55) 0%, rgba(11,13,10,0) 22%, rgba(11,13,10,0) 50%, rgba(11,13,10,0.85) 78%, rgba(11,13,10,0.95) 100%); }
.card { position: absolute; left: 70px; right: 70px; bottom: 300px; }
.card .head { display: inline-block; background: var(--ink); border-left: 16px solid var(--lime); padding: 20px 36px 8px 30px; font-family: "Bebas"; font-size: 128px; line-height: 0.95; letter-spacing: 1px; }
.card .sub { display: inline-block; margin-top: 18px; background: var(--lime); color: var(--ink); padding: 10px 28px 12px; font-size: 52px; font-weight: 600; letter-spacing: 0.5px; }
#logo { position: absolute; top: 80px; left: 60px; border: 5px solid var(--lime); padding: 8px 22px 10px; text-align: center; background: rgba(11,13,10,0.85); z-index: 5; }
#phone { position: absolute; top: 96px; right: 60px; display: flex; align-items: center; gap: 12px; background: rgba(11,13,10,0.85); border: 3px solid var(--lime); border-radius: 44px; padding: 12px 26px 12px 20px; font-family: "Bebas"; font-size: 54px; line-height: 1; letter-spacing: 1px; color: var(--white); z-index: 5; }
#phone svg { width: 40px; height: 40px; flex: none; }
#logo .word { font-family: "Bebas"; font-size: 74px; line-height: 0.9; letter-spacing: 1px; white-space: nowrap; }
#logo .word .oxy { color: var(--lime); }
#logo .tag { font-family: "Bebas"; font-size: 22px; letter-spacing: 2px; white-space: nowrap; }
#dots { position: absolute; left: 0; right: 0; bottom: 200px; display: flex; justify-content: center; gap: 18px; z-index: 5; }
#dots i { width: 70px; height: 10px; border-radius: 5px; background: rgba(255,255,255,0.3); overflow: hidden; position: relative; }
#dots i b { position: absolute; inset: 0; background: var(--lime); transform-origin: left center; transform: scaleX(0); }
</style>
</head>
<body>
<div id="root" data-composition-id="main" data-start="0" data-duration="__DUR__" data-width="1080" data-height="1920">
__SCENES__
<div id="logo" class="clip" data-start="0" data-duration="__DUR__">
<div class="word"><span class="oxy">OXY</span>GREEN</div>
<div class="tag">TURF CLEANER & DEODORIZER</div>
</div>
<div id="phone" class="clip" data-start="0" data-duration="__DUR__"><svg viewBox="0 0 24 24" fill="#7dc242"><path d="M6.6 10.8a15.2 15.2 0 0 0 6.6 6.6l2.2-2.2a1 1 0 0 1 1-.25 11.4 11.4 0 0 0 3.6.57 1 1 0 0 1 1 1V20a1 1 0 0 1-1 1A17 17 0 0 1 3 4a1 1 0 0 1 1-1h3.5a1 1 0 0 1 1 1c0 1.25.2 2.45.57 3.57a1 1 0 0 1-.25 1z"/></svg>(800) 625-8170</div>
<div id="dots" class="clip" data-start="0" data-duration="__DUR__">__DOTS__</div>
</div>
<script>
const tl = gsap.timeline({ paused: true });
const scenes = __TIMING__;
tl.fromTo("#logo", { opacity: 0, y: -30 }, { opacity: 1, y: 0, duration: 0.5, ease: "power2.out" }, 0);
tl.fromTo("#phone", { opacity: 0, y: -30 }, { opacity: 1, y: 0, duration: 0.5, ease: "power2.out" }, 0.15);
scenes.forEach((s, i) => {
const id = "#s" + i;
if (i > 0) tl.fromTo(id, { opacity: 0 }, { opacity: 1, duration: 0.35, ease: "power1.out" }, s.start);
tl.fromTo(id + " .head", { opacity: 0, x: -80 }, { opacity: 1, x: 0, duration: 0.45, ease: "power3.out" }, s.start + 0.15);
tl.fromTo(id + " .sub", { opacity: 0, y: 30 }, { opacity: 1, y: 0, duration: 0.4, ease: "power3.out" }, s.start + 0.4);
tl.to(id + " .card", { opacity: 0, y: -20, duration: 0.25, ease: "power1.in" }, s.start + s.dur - 0.3);
tl.fromTo("#d" + i, { scaleX: 0 }, { scaleX: 1, duration: s.dur, ease: "none" }, s.start);
});
window.__timelines["main"] = tl;
tl.seek(0);
</script>
</body>
</html>