📐 Vertical format — 1080×1920 with useVideoConfig
The Reel starts with the definition of the Composition: width: 1080, height: 1920. Everything inside the component reads these dimensions via useVideoConfig() to adapt — larger fonts, smaller margins, and content vertically centered in the upper third (where the user’s thumb is).
// Root.tsx — declaração do formato <Composition id="Reel" component={ReelVideo} width={1080} height={1920} fps={30} durationInFrames={900} // 30 s /> // Reel.tsx — layout responsivo const { width, height } = useVideoConfig(); // fonte escala com a largura const baseFontSize = width * 0.055; // ~60px em 1080px // conteúdo no terço superior (fora da área do polegar) const contentTop = height * 0.15;
📱 9:16 layout rules
- Top third (0–30%): title and main text — most visible area
- Middle third (30–70%): visual/image — eye’s focal area
- Bottom third (70–100%): CTA and subscribe — thumb zone, interaction
- Minimum font: 60px at 1080px (width * 0.055) — legible on a small phone
💬 Animated caption — typewriter and bounce-text
85% of Reels are watched without sound. This means the text is the audio of the video. The typewriter-subtitle.tsx reveals the text letter by letter, while the bounce-text.tsx makes each word enter with a small bounce — both create the feeling that someone is "writing live".
const words = text.split(" "); const FRAMES_PER_WORD = 8; // ritmo: 1 palavra a cada 8 frames {words.map((word, i) => { const startFrame = i * FRAMES_PER_WORD; const opacity = interpolate( frame, [startFrame, startFrame + 6], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp" } ); // bounce: entra de baixo const y = interpolate( frame, [startFrame, startFrame + 10], [20, 0], { easing: Easing.out(Easing.back(1.5)), extrapolateLeft: "clamp", extrapolateRight: "clamp" } ); return <span key={i} style={{ opacity, transform: `translateY(${y}px)`, display: "inline-block", margin: "0 4px" }}>{word}</span>; })}
💡 Pacing: 8 frames per word = 0.27 s
At 30fps, 8 frames per word produces natural, fluid reading. For impactful phrases that need more emphasis, use 12–15 frames per word. For quick lists (“easy · fast · cheap”), use 5–6 frames. The text rhythm should mimic the rhythm of speech.
⚡ Highlight glitch — visual impact in the first frames
The Reels algorithm measures retention in the first 3 seconds. The glitch-text.tsx creates an "interference" effect on the video's keyword: rapid color shifts (channel offset) for 2–4 frames, creating visual impact that immediately grabs attention.
✓ A glitch that works
- ✓Glitch in the first 0–15 frames — grabs attention before the scroll.
- ✓Small offset (3–8px) — noticeable without being nauseating.
- ✓random("glitch-N") with a seed — same glitch in every render.
✗ A glitch that drives people away
- ✗Glitch throughout the video — tiring and looks like a bug, not an effect.
- ✗Large offset (20px+) — makes the text unreadable.
- ✗Math.random() without a seed — text "flashes" uncontrollably during rendering.
Frame 0–3: intense glitch
Three text layers randomly offset in X and Y (but seeded). Colors: amber, cyan, and white, separated by 3–6px.
Frame 4–6: residual glitch
Offset drops to 1–2px. The glitch's “cure” is just as important as the glitch — stabilization reinforces the word in memory.
Frame 7+: stable text
The main text stays steady for the rest of the scene. The glitch effect can briefly reappear when a new phrase appears.
🎵 Sound-wave visual — rhythm without audio
O sound-wave.tsx renders a row of bars that oscillate with Math.sin(), simulating an audio visualization. In a Reel without sound, this element signals “this video has energy”—it’s the visual equivalent of a music beat.
const frame = useCurrentFrame(); const BAR_COUNT = 32; const MAX_H = 80; // px, relativo ao height do container {Array.from({ length: BAR_COUNT }).map((_, i) => { const seed = random(`wave-${i}`); // fase aleatória por barra const barH = Math.abs( Math.sin(frame * 0.15 + seed * Math.PI * 2) ) * MAX_H + 4; // mínimo 4px para não sumir return <div key={i} style={{ width: 4, height: barH, background: i % 3 === 0 ? "#38bdf8" : "#fbbf24", borderRadius: 2 }} />; })}
🫧 Bokeh Background — Synthetic Depth of Field
O bokeh-circles.tsx generates blurred circles floating in the background — the bokeh effect of a real camera, but 100% computational. Each circle has a random (seeded) size, position, opacity, and vertical speed, creating depth of field without a physical camera.
🫧 How bokeh is generated
- Position: random("bokeh-x-N") and random("bokeh-y-N") — fixed, deterministic
- Size: random("bokeh-r-N") * 80 + 20 — between 20 and 100px in radius
- Floating: translateY = -frame * random("bokeh-speed-N") * 0.3 — moves up slowly
- Reappearance: when y < -r, reposition to height + r (loop)
- Blur: filter: blur(Npx) — between 8 and 20px to look out of focus
🔔 Subscribe reminder — CTA in the last 5 s
O subscribe-reminder.tsx appears in the last 150 frames (5 s) of the Reel — a bell + “Subscribe” text animation that doesn’t compete with the main content but is there when the viewer is most engaged (because they watched to the end).
const { durationInFrames } = useVideoConfig(); const frame = useCurrentFrame(); // aparece nos últimos 150 frames return ( <Sequence from={durationInFrames - 150}> <SubscribeWidget /> </Sequence> ); // SubscribeWidget — sino com shake e texto const bellFrame = useCurrentFrame(); // local frame (0–150) const scale = spring({ frame: bellFrame, fps, config: { damping: 10, stiffness: 200 } }); // shake: oscila 3x por segundo const shakeX = Math.sin(bellFrame * 0.5) * interpolate(bellFrame, [0, 10], [8, 0], { extrapolateRight: "clamp" });
💡 Why the last fifth?
Viewers who make it to the Reel’s last 5 s are already “warm”—they approved the content. That’s the best time to ask them to take action. Asking them to subscribe before then feels like spam; after that, there’s no time to react. The right timing is what separates an effective CTA from an intrusion.
🏆 Module Summary — and Course Summary
🎓 You completed Track 4 — and the course!
You’ve completed all 4 tracks: Fundamentals (T1), Assets and Templates (T2), Combining and Composition (T3), and now Complete Projects (T4). With the library’s 81 templates and the techniques you’ve learned, you’re equipped to create any programmatic video — from channel openers to viral Reels.