mati-teaser-v3.1.mp4
88 seconds. 1,558 lines of TSX. 13 animated beats. Zero After Effects.
The full source code for MATI's product teaser video — a polished, 88-second animated explainer built entirely in code using Remotion and Claude Code.
No motion designers. No After Effects. No Figma-to-video plugins. Just React components rendered to MP4.
This repo is open source so other founders can fork it and build their own launch videos the same way.
| Stat | Value |
|---|---|
| Duration | 88s (2,641 frames @ 30fps) |
| Source | 1,558 lines of TSX |
| Scenes | 13 animated beats |
| Resolution | 1920×1080 |
| Transitions | Spring physics + crossfades |
| Design cost | €0 |
| Time to build | One Claude Code conversation |
# Clone
git clone https://github.com/meetmati-ai/MATI-teaser.git
cd MATI-teaser
# Install
npm install
# Preview in browser (hot reload)
npm run dev
# Render to MP4
npx remotion render src/index.ts MatiTeaserV3 out/teaser.mp4 --codec=h264 --crf=18src/
├── index.ts # Remotion entry point
├── Root.tsx # Composition registry (all videos)
├── MatiTeaserV3.tsx # ← The main teaser (1,558 lines, 13 beats)
├── MatiLaunch.tsx # Shorter 37s product launch cut
├── MatiTeaser.tsx # Original v1 teaser
├── KineticHero.tsx # Kinetic typography component
└── BeatSamples.tsx # Individual beat previews
public/
├── logos/ # SVG logos used in product UI beats
├── mati-icon.svg # MATI brand icon
└── music.mp3 # Background audio track
remotion.config.ts # Remotion CLI config
package.json # Dependencies & scripts
Every scene ("beat") is an isolated React component that receives a duration prop:
const Beat1: React.FC<{ duration: number }> = ({ duration }) => {
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
// Spring-based entrance animation
const titleScale = spring({ frame, fps, config: { damping: 18 } });
return (
<Scene duration={duration}>
<h1 style={{ transform: `scale(${titleScale})` }}>
The best product no longer wins.
</h1>
</Scene>
);
};Beats are composed using Remotion's TransitionSeries with crossfades:
<TransitionSeries>
<TransitionSeries.Sequence durationInFrames={D.beat1}>
<Beat1 duration={D.beat1} />
</TransitionSeries.Sequence>
<TransitionSeries.Transition
presentation={fade()}
timing={linearTiming({ durationInFrames: 12 })}
/>
<TransitionSeries.Sequence durationInFrames={D.beat2}>
<Beat2 duration={D.beat2} />
</TransitionSeries.Sequence>
{/* ... */}
</TransitionSeries>| Component | Purpose |
|---|---|
Scene |
Fade-in/out wrapper with scale animation |
MatiWave |
Animated sound wave logo (the MATI brand mark) |
GridOverlay |
Subtle grid pattern for depth |
AmbientGlow |
Floating radial gradients for atmosphere |
One object controls the entire visual identity:
const C = {
bg: '#FFFFFF',
fg: '#1E2530',
turq: '#2DD4A0', // Primary accent
turqDark: '#059669', // Emphasis
red: '#EF4444', // Pain points, cost
dark: '#0B0F15', // Product UI beats
// ...
};Change this palette → entire video updates.
# Fork this repo, then:
git clone https://github.com/YOUR_ORG/YOUR-teaser.git
cd YOUR-teaser && npm installEdit the palette in src/MatiTeaserV3.tsx:
const C = {
bg: '#FFFFFF', // Your background
fg: '#1A1A2E', // Your text color
turq: '#6C63FF', // Your brand accent (was MATI green)
turqDark: '#5A52D5', // Your darker accent
red: '#FF6B6B', // Your warning/cost color
// ...
};Each beat follows this pattern:
const YourBeat: React.FC<{ duration: number }> = ({ duration }) => {
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
// Entrance animation (spring = cinematic, no keyframes)
const enter = spring({ frame, fps, config: { damping: 16, stiffness: 80 } });
return (
<Scene duration={duration} bg={C.bg}>
{/* Your content here */}
</Scene>
);
};The beat structure follows a proven startup teaser formula:
1. HOOK — Bold statement that stops the scroll
2. PAIN — Show the problem visually (not just text)
3. AMPLIFY — Make the pain feel worse / universal
4. REFRAME — Challenge existing solutions
5. VISION — "What if..." moment
6. REVEAL — Your product name + positioning
7–11. DEMO — Show the product working (2-4 beats)
12. PROOF — Social proof, metrics, or pricing
13. CTA — Clear next step
# Preview with hot reload
npm run dev
# Render final video
npx remotion render src/index.ts YourComposition out/video.mp4 --codec=h264 --crf=18
# Render a specific beat for testing
npx remotion render src/index.ts YourComposition out/test.mp4 \
--frames=0-120 --codec=h264These are the actual prompts used in the Claude Code conversation that generated this video. Use them as templates:
Create a Remotion project for a startup product teaser video.
1920x1080, 30fps. Use spring physics for all animations (never linear easing).
TypeScript + React. Design system with a single color palette object.
Build a teaser video with this narrative arc:
- Hook: "The best product no longer wins"
- Pain: Show siloed marketing tools in a grid, each failing
- Reframe: "AI can automate tasks. But tasks aren't marketing."
- Vision: "What if marketing ran itself?"
- Product reveal: Logo animation with glow
- Demo: Show the autonomous agent dashboard, content output, calendar
- CTA: Pricing comparison + URL
Each scene should be a separate React component. Use TransitionSeries
with 12-frame crossfades between beats.
Beat 6B (agent dashboard) needs more visual complexity:
- Stagger 4 capability cards from the left with spring physics
- Add a typing animation showing real-time agent activity
- Include a progress bar that fills to 100%
- Keep it under 340 frames (11.3 seconds)
Add these production touches to all beats:
- GridOverlay component (subtle grid pattern, 4% opacity)
- AmbientGlow floating radial gradients that drift slowly
- The MATI logo should be an animated sound wave (5 bars pulsing)
- All text entrances: spring with damping 16-22, staggered by 6-8 frames
The video feels too long. Compress beats 7a-7d:
- 7a (content showcase): cut from 500 to 420 frames
- 7b (calendar): cut from 350 to 270 frames
- 7c (growth graph): cut from 250 to 200 frames
Recalculate TEASER_V3_DURATION as the sum of all beat durations
minus (number_of_transitions × transition_duration).
| Concept | What it does | Example |
|---|---|---|
useCurrentFrame() |
Current frame number (0-indexed) | Drive any animation |
spring() |
Physics-based easing | spring({ frame, fps, config: { damping: 16 } }) |
interpolate() |
Map frame range to value range | interpolate(frame, [0, 30], [0, 1]) |
<Sequence> |
Show component at specific time | <Sequence from={100}> |
<TransitionSeries> |
Chain scenes with transitions | Crossfades, slides, wipes |
staticFile() |
Reference files in public/ |
staticFile('music.mp3') |
<Audio> |
Add audio with volume control | <Audio src={...} volume={0.8} /> |
Full docs: remotion.dev/docs
-
Spring physics > linear easing. One
spring()call with good damping (14–22) looks more cinematic than any cubic-bezier you'll hand-tune. -
One file is fine. Don't over-engineer the structure. A single 1,500-line file with all beats is easier to iterate on than 13 separate files when you're moving fast.
-
Design tokens first. Define your palette as a
const C = {...}object before writing any beats. Rebranding becomes a 30-second edit. -
Test beats in isolation. Use
--frames=0-120to render just the first beat while iterating. Full renders take 2-3 minutes. -
Music makes it. A good background track elevates everything. Add it via
<Audio src={staticFile('music.mp3')} />and adjustvolumeper beat if needed. -
Let Claude Code handle the math. Stagger timings, spring configs, interpolation ranges — describe what you want in English and let the AI compute the frame numbers.
npm run dev # Remotion Studio (live preview in browser)
npm run render # Render MatiTeaser (original v1)
npm run render:launch # Render MatiLaunch (37s cut)
# Custom render (the main teaser v3)
npx remotion render src/index.ts MatiTeaserV3 out/mati-teaser-v3.mp4 --codec=h264 --crf=18- Remotion — React framework for programmatic video
- React 18 — Component rendering
- TypeScript — Type safety
- @remotion/transitions — Crossfade transitions
- @remotion/google-fonts — Font loading
MIT — fork it, rebrand it, ship your own launch video.
Built by Aditya Gudipudi · MATI