Files
hyperframes/docs/catalog/blocks/heygen-avatar-promo-card.mdx
T

481 lines
17 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: "HeyGen Avatar Promo Card"
description: "A portrait HeyGen offer card pairs a moving avatar mosaic with bold promotional typography and a branded callout"
---
import { InstallCommand } from "/snippets/install-command.jsx";
<video className="w-full aspect-video rounded-xl object-cover bg-zinc-100 dark:bg-zinc-800" src="https://static.heygen.ai/hyperframes-oss/docs/images/catalog/blocks/heygen-avatar-promo-card.mp4" poster="https://static.heygen.ai/hyperframes-oss/docs/images/catalog/blocks/heygen-avatar-promo-card.png" autoPlay muted loop playsInline />
## Install
<InstallCommand command="npx hyperframes add heygen-avatar-promo-card" item="heygen-avatar-promo-card" />
That writes `compositions/heygen-avatar-promo-card.html`, plus 15 supporting files under `assets/` and `assets/fonts/`.
## Add it to your video
It runs for 10 seconds at 1080×1920. Paste this into your composition:
```html index.html
<div
data-composition-id="heygen-avatar-promo-card"
data-composition-src="compositions/heygen-avatar-promo-card.html"
data-start="0"
data-duration="10"
data-track-index="1"
data-width="1080"
data-height="1920"
></div>
```
Move it in time with `data-start`. Put it on a different timeline row with
`data-track-index`. See [data attributes](/concepts/data-attributes) for the rest.
## Source
<Accordion title={`heygen-avatar-promo-card.html`}>
```html
<!doctype html>
<html
lang="en"
data-resolution="portrait"
data-composition-variables='[
{ "id": "brandLogo", "type": "image", "role": "content", "label": "Brand logo", "description": "Horizontal transparent wordmark used in the header and belt.", "default": "assets/heygen-logo.svg" },
{ "id": "titleLine1", "type": "string", "role": "content", "label": "Headline line 1", "description": "First headline line.", "default": "Your avatar," },
{ "id": "titleLine2", "type": "string", "role": "content", "label": "Headline line 2", "description": "Second headline line.", "default": "by HeyGen." },
{ "id": "subhead", "type": "string", "role": "content", "label": "Subhead", "description": "Supporting line under the headline.", "default": "AI video, camera-free." },
{ "id": "pill1", "type": "string", "role": "content", "label": "Pill 1", "description": "First feature pill.", "default": "4K AVATARS" },
{ "id": "pill2", "type": "string", "role": "content", "label": "Pill 2", "description": "Second feature pill.", "default": "NO CAMERA NEEDED" },
{ "id": "offerValue", "type": "string", "role": "content", "label": "Offer value", "description": "Large offer value in the light tile.", "default": "25%" },
{ "id": "offerSuffix", "type": "string", "role": "content", "label": "Offer suffix", "description": "Large offer suffix in the adjacent light tile.", "default": "OFF" },
{ "id": "codeLabel", "type": "string", "role": "content", "label": "Promo code label", "description": "Small label above the promo code.", "default": "CODE" },
{ "id": "promoPrefix", "type": "string", "role": "content", "label": "Promo code prefix", "description": "Accent-colored promo-code prefix.", "default": "GEN" },
{ "id": "promoSuffix", "type": "string", "role": "content", "label": "Promo code suffix", "description": "Light promo-code suffix.", "default": "25" },
{ "id": "canvasColor", "type": "color", "role": "style", "label": "Canvas color", "description": "Main card background.", "default": "#eaf6fa" },
{ "id": "inkColor", "type": "color", "role": "style", "label": "Ink color", "description": "Primary headline, pill, and offer ink.", "default": "#0a1418" },
{ "id": "mutedInkColor", "type": "color", "role": "style", "label": "Muted ink color", "description": "Subhead ink.", "default": "#47545b" },
{ "id": "accentColor", "type": "color", "role": "style", "label": "Accent color", "description": "Brand accent used by tiles and promo-code prefix.", "default": "#00c3ff" },
{ "id": "lightTileColor", "type": "color", "role": "style", "label": "Light tile color", "description": "Light belt-tile surface.", "default": "#f7fcfe" },
{ "id": "darkTileColor", "type": "color", "role": "style", "label": "Dark tile color", "description": "Dark belt-tile surface.", "default": "#0b1215" }
]'
>
<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>
/* The source project used proprietary HeyGen brand fonts. These OFL faces
keep the public catalog block self-contained and redistributable. */
@font-face {
font-family: "AvatarDisplay";
src: url("assets/fonts/eb-garamond-latin-400-normal.woff2") format("woff2");
font-weight: 400 600;
font-display: block;
}
@font-face {
font-family: "AvatarDisplay";
src: url("assets/fonts/eb-garamond-latin-700-normal.woff2") format("woff2");
font-weight: 700 900;
font-display: block;
}
@font-face {
font-family: "AvatarSans";
src: url("assets/fonts/inter-latin-400-normal.woff2") format("woff2");
font-weight: 400;
font-display: block;
}
@font-face {
font-family: "AvatarSans";
src: url("assets/fonts/inter-latin-500-normal.woff2") format("woff2");
font-weight: 500;
font-display: block;
}
@font-face {
font-family: "AvatarSans";
src: url("assets/fonts/inter-latin-600-normal.woff2") format("woff2");
font-weight: 600 900;
font-display: block;
}
html,
body {
margin: 0;
padding: 0;
background: #000;
font-family: "AvatarSans", sans-serif;
}
/* palette: canvas #EAF6FA · ink #0A1418 · light tile #F7FCFE · dark tile #0B1215 ·
cyan #00C3FF (fills / dark-bg display only) · subhead #47545B */
#heygen-avatar-promo-card {
position: relative;
width: 1080px;
height: 1920px;
overflow: hidden;
--apc-canvas: #eaf6fa;
--apc-ink: #0a1418;
--apc-muted: #47545b;
--apc-accent: #00c3ff;
--apc-light-tile: #f7fcfe;
--apc-dark-tile: #0b1215;
}
.bgfill {
position: absolute;
inset: 0;
background: var(--apc-canvas);
}
.hdr {
position: absolute;
left: 0;
width: 1080px;
text-align: center;
color: var(--apc-ink);
}
#apc-hdr-logo {
top: 118px;
height: 44px;
}
#apc-hdr-logo img {
height: 44px;
}
#apc-hdr-title {
top: 205px;
font-family: "AvatarDisplay", serif;
font-weight: 700;
font-size: 148px;
line-height: 150px;
letter-spacing: -0.02em;
}
#apc-hdr-subhead {
top: 524px;
font-family: "AvatarSans", sans-serif;
font-weight: 500;
font-size: 37px;
color: var(--apc-muted);
letter-spacing: -0.01em;
}
#apc-hdr-pills {
top: 1590px;
display: flex;
justify-content: center;
gap: 28px;
}
.pill {
border: 2px solid var(--apc-ink);
border-radius: 999px;
padding: 0 42px;
height: 92px;
line-height: 88px;
font-family: "AvatarSans", sans-serif;
font-weight: 600;
font-size: 27px;
letter-spacing: 0.12em;
color: var(--apc-ink);
}
#apc-belt-linear {
position: absolute;
top: 640px;
left: 0;
width: 2600px;
height: 784px;
}
#apc-belt-entry {
position: absolute;
inset: 0;
}
.tile {
position: absolute;
width: 362px;
height: 380px;
border-radius: 30px;
overflow: hidden;
display: block;
}
.row1 {
top: 0;
}
.row2 {
top: 404px;
}
.tile video {
width: 362px;
height: 380px;
object-fit: cover;
display: block;
}
.light {
background: var(--apc-light-tile);
}
.dark {
background: var(--apc-dark-tile);
}
.cyan {
background: var(--apc-accent);
}
.serif-tile {
display: flex;
align-items: center;
justify-content: center;
font-family: "AvatarDisplay", serif;
font-weight: 500;
font-size: 165px;
color: var(--apc-ink);
}
.brand-tile {
display: flex;
align-items: center;
justify-content: center;
}
.brand-tile img {
width: 240px;
}
.code-tile {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 26px;
}
.code-tile .code {
font-family: "AvatarSans", sans-serif;
font-weight: 600;
font-size: 26px;
letter-spacing: 0.42em;
color: #8fa3ad;
text-indent: 0.42em;
}
.code-tile .promo {
font-family: "AvatarSans", sans-serif;
font-weight: 800;
font-size: 92px;
letter-spacing: -0.01em;
}
.code-tile .promo .gen {
color: var(--apc-accent);
}
.code-tile .promo .n25 {
color: #fbfcfc;
}
</style>
</head>
<body>
<div
id="heygen-avatar-promo-card"
data-composition-id="heygen-avatar-promo-card"
data-start="0"
data-width="1080"
data-height="1920"
data-duration="10"
data-fps="25"
>
<div class="bgfill"></div>
<!-- belt: geometry + motion law measured from the reference (see reversal spec) -->
<div id="apc-belt-linear">
<div id="apc-belt-entry">
<!-- row 1 -->
<div class="tile row1 cyan brand-tile" style="left: 139.1px">
<img src="assets/heygen-logo.svg?t=1" alt="" />
</div>
<video
class="tile row1 clip"
id="apc-v-r1k1"
src="assets/av_r1k1.mp4"
style="left: 523.4px"
data-start="0"
data-duration="8.60"
data-track-index="1"
muted
playsinline
></video>
<div id="apc-offer-value" class="tile row1 light serif-tile" style="left: 907.7px">
25%
</div>
<video
class="tile row1 clip"
id="apc-v-r1k3"
src="assets/av_r1k3.mp4"
style="left: 1292px"
data-start="1.44"
data-duration="8.56"
data-track-index="2"
muted
playsinline
></video>
<video
class="tile row1 clip"
id="apc-v-r1k4"
src="assets/av_r1k4.mp4"
style="left: 1676.3px"
data-start="5.56"
data-duration="4.44"
data-track-index="3"
muted
playsinline
></video>
<div class="tile row1 cyan" style="left: 2060.6px"></div>
<!-- row 2 -->
<video
class="tile row2 clip"
id="apc-v-r2k0"
src="assets/av_r2k0.mp4"
style="left: 139.1px"
data-start="0"
data-duration="4.48"
data-track-index="4"
muted
playsinline
></video>
<div
id="apc-offer-suffix"
class="tile row2 light serif-tile"
style="left: 523.4px; font-size: 146px"
>
OFF
</div>
<video
class="tile row2 clip"
id="apc-v-r2k2"
src="assets/av_r2k2.mp4"
style="left: 907.7px"
data-start="0"
data-duration="10"
data-track-index="5"
muted
playsinline
></video>
<div class="tile row2 dark code-tile" style="left: 1292px">
<div id="apc-code-label" class="code">CODE</div>
<div class="promo">
<span id="apc-promo-prefix" class="gen">GEN</span
><span id="apc-promo-suffix" class="n25">25</span>
</div>
</div>
<div class="tile row2 light brand-tile" style="left: 1676.3px">
<img src="assets/heygen-logo.svg?t=2" alt="" />
</div>
<div class="tile row2 dark" style="left: 2060.6px"></div>
</div>
</div>
<!-- header block -->
<div class="hdr" id="apc-hdr-logo"><img src="assets/heygen-logo.svg" alt="HeyGen" /></div>
<div class="hdr" id="apc-hdr-title">
Your avatar,
<div id="apc-title-line-2">by HeyGen.</div>
</div>
<div class="hdr" id="apc-hdr-subhead">AI video, camera-free.</div>
<div class="hdr" id="apc-hdr-pills">
<div id="apc-pill-1" class="pill">4K AVATARS</div>
<div id="apc-pill-2" class="pill">NO CAMERA NEEDED</div>
</div>
<audio
id="apc-bgm"
class="clip"
src="assets/bgm.m4a"
data-start="0"
data-duration="10"
data-track-index="0"
></audio>
</div>
<script>
const variables =
window.__hyperframes && typeof window.__hyperframes.getVariables === "function"
? window.__hyperframes.getVariables()
: {};
const root = document.getElementById("heygen-avatar-promo-card");
const text = (id, fallback) =>
typeof variables[id] === "string" && variables[id].trim() ? variables[id] : fallback;
const color = (id, fallback) => text(id, fallback);
root.style.setProperty("--apc-canvas", color("canvasColor", "#eaf6fa"));
root.style.setProperty("--apc-ink", color("inkColor", "#0a1418"));
root.style.setProperty("--apc-muted", color("mutedInkColor", "#47545b"));
root.style.setProperty("--apc-accent", color("accentColor", "#00c3ff"));
root.style.setProperty("--apc-light-tile", color("lightTileColor", "#f7fcfe"));
root.style.setProperty("--apc-dark-tile", color("darkTileColor", "#0b1215"));
document.querySelectorAll(".brand-tile img, #apc-hdr-logo img").forEach((image) => {
image.src = text("brandLogo", "assets/heygen-logo.svg");
});
document.getElementById("apc-hdr-title").firstChild.nodeValue = text(
"titleLine1",
"Your avatar,",
);
document.getElementById("apc-title-line-2").textContent = text("titleLine2", "by HeyGen.");
document.getElementById("apc-hdr-subhead").textContent = text(
"subhead",
"AI video, camera-free.",
);
document.getElementById("apc-pill-1").textContent = text("pill1", "4K AVATARS");
document.getElementById("apc-pill-2").textContent = text("pill2", "NO CAMERA NEEDED");
document.getElementById("apc-offer-value").textContent = text("offerValue", "25%");
document.getElementById("apc-offer-suffix").textContent = text("offerSuffix", "OFF");
document.getElementById("apc-code-label").textContent = text("codeLabel", "CODE");
document.getElementById("apc-promo-prefix").textContent = text("promoPrefix", "GEN");
document.getElementById("apc-promo-suffix").textContent = text("promoSuffix", "25");
const tl = gsap.timeline({ paused: true });
// Belt conveyor — measured from reference: 93.601 px/s constant, leftward
tl.fromTo("#apc-belt-linear", { x: 0 }, { x: -936.01, duration: 10, ease: "none" }, 0);
// Belt entry — measured offset table, one keyframe per source frame, linear between
const entryX = [
0, -11.39, -21.64, -30.9, -39.04, -46.29, -52.55, -57.98, -62.72, -66.71, -69.99, -72.75,
-74.86, -76.52, -77.85, -78.8, -79.36, -79.75, -79.87, -79.94, -80.0,
];
for (let i = 1; i < entryX.length; i++) {
tl.fromTo(
"#apc-belt-entry",
{ x: entryX[i - 1] },
{ x: entryX[i], duration: 0.04, ease: "none", immediateRender: i === 1 },
(i - 1) * 0.04,
);
}
// Header waterfall — measured fades
tl.fromTo(
"#apc-hdr-logo",
{ autoAlpha: 0 },
{ autoAlpha: 1, duration: 0.4, ease: "power2.out" },
0.0,
);
tl.fromTo(
"#apc-hdr-title",
{ autoAlpha: 0 },
{ autoAlpha: 1, duration: 0.6, ease: "power2.out" },
0.1,
);
tl.fromTo(
"#apc-hdr-subhead",
{ autoAlpha: 0 },
{ autoAlpha: 1, duration: 0.4, ease: "power2.out" },
0.5,
);
// pills static from frame 0
window.__timelines = window.__timelines || {};
window.__timelines["heygen-avatar-promo-card"] = tl;
</script>
</body>
</html>
```
</Accordion>
{/* hf:generated-footer */}
Tagged `showcase` `avatar` `promotion` `vertical`.
Created by HeyGen.
## Related topics
- [Browse the complete Catalog](/catalog)
- [Add assets and Catalog items in Studio](/studio/assets-and-blocks)
- [Build a richer composition](/go-further)