diff --git a/apps/videos/src/compositions/promo-teaser/scenes/AmbientOpenScene.tsx b/apps/videos/src/compositions/promo-teaser/scenes/AmbientOpenScene.tsx
new file mode 100644
index 00000000..0d2d80de
--- /dev/null
+++ b/apps/videos/src/compositions/promo-teaser/scenes/AmbientOpenScene.tsx
@@ -0,0 +1,58 @@
+import type React from "react";
+import { AbsoluteFill, interpolate, useCurrentFrame } from "remotion";
+import { GradientBlob } from "@/components/GradientBlob";
+
+const BLOBS = [
+ {
+ color: "#f59e0b",
+ radius: 200,
+ cx: 300,
+ cy: 400,
+ a: 1,
+ b: 2,
+ phaseX: 0,
+ phaseY: 0,
+ amplitudeX: 60,
+ amplitudeY: 40,
+ },
+ {
+ color: "#f97316",
+ radius: 150,
+ cx: 750,
+ cy: 250,
+ a: 2,
+ b: 1,
+ phaseX: 1.2,
+ phaseY: 0.8,
+ amplitudeX: 50,
+ amplitudeY: 60,
+ },
+ {
+ color: "#d97706",
+ radius: 180,
+ cx: 540,
+ cy: 700,
+ a: 1,
+ b: 1,
+ phaseX: 2.4,
+ phaseY: 1.6,
+ amplitudeX: 70,
+ amplitudeY: 50,
+ },
+];
+
+export const AmbientOpenScene: React.FC = () => {
+ const frame = useCurrentFrame();
+ const fadeIn = interpolate(frame, [0, 45], [0, 1], {
+ extrapolateLeft: "clamp",
+ extrapolateRight: "clamp",
+ });
+
+ return (
+
+ {BLOBS.map((blob, i) => (
+
+ ))}
+
+ );
+};
diff --git a/apps/videos/src/compositions/promo-teaser/scenes/CTAScene.tsx b/apps/videos/src/compositions/promo-teaser/scenes/CTAScene.tsx
new file mode 100644
index 00000000..63f7124a
--- /dev/null
+++ b/apps/videos/src/compositions/promo-teaser/scenes/CTAScene.tsx
@@ -0,0 +1,60 @@
+import type React from "react";
+import { AbsoluteFill, interpolate, spring, useCurrentFrame, useVideoConfig } from "remotion";
+import { COLOR } from "@/lib/colors";
+import { FONT } from "@/lib/fonts";
+import { SPRING } from "@/lib/motion";
+
+export const CTAScene: React.FC = () => {
+ const frame = useCurrentFrame();
+ const { fps } = useVideoConfig();
+
+ const pillScale = spring({ frame, fps, config: SPRING.popIn });
+ const urlOpacity = interpolate(frame, [15, 25], [0, 0.7], {
+ extrapolateLeft: "clamp",
+ extrapolateRight: "clamp",
+ });
+ const fadeOut = interpolate(frame, [60, 90], [1, 0], {
+ extrapolateLeft: "clamp",
+ extrapolateRight: "clamp",
+ });
+ const glowOpacity = interpolate(Math.sin(frame * 0.1), [-1, 1], [0.3, 0.6]);
+
+ return (
+
+
+ Get it free
+
+
+
+
+
+ snapotter.com
+
+
+ );
+};
diff --git a/apps/videos/src/compositions/promo-teaser/scenes/LogoRevealScene.tsx b/apps/videos/src/compositions/promo-teaser/scenes/LogoRevealScene.tsx
new file mode 100644
index 00000000..f7d7fc93
--- /dev/null
+++ b/apps/videos/src/compositions/promo-teaser/scenes/LogoRevealScene.tsx
@@ -0,0 +1,18 @@
+import type React from "react";
+import { AbsoluteFill } from "remotion";
+import { LogoReveal } from "@/components/LogoReveal";
+
+export const LogoRevealScene: React.FC = () => {
+ return (
+
+
+
+ );
+};
diff --git a/apps/videos/src/compositions/promo-teaser/scenes/NumberPunchScene.tsx b/apps/videos/src/compositions/promo-teaser/scenes/NumberPunchScene.tsx
new file mode 100644
index 00000000..3fcb9c95
--- /dev/null
+++ b/apps/videos/src/compositions/promo-teaser/scenes/NumberPunchScene.tsx
@@ -0,0 +1,45 @@
+import type React from "react";
+import { AbsoluteFill, interpolate, useCurrentFrame } from "remotion";
+import { NumberPunch } from "@/components/NumberPunch";
+import { COLOR } from "@/lib/colors";
+
+const PUNCHES = [
+ { number: "49", descriptor: "tools", frame: 0, size: 120, shake: 2 },
+ { number: "15", descriptor: "AI models", frame: 37, size: 120, shake: 2 },
+ { number: "55+", descriptor: "formats", frame: 74, size: 120, shake: 2 },
+ { number: "1", descriptor: "container", frame: 111, size: 144, shake: 3 },
+];
+
+export const NumberPunchScene: React.FC = () => {
+ const frame = useCurrentFrame();
+
+ return (
+
+ {PUNCHES.map((p, i) => {
+ const visible = frame >= p.frame && frame < p.frame + 37;
+ const flashStart = p.frame - 2;
+ const flashOpacity =
+ i > 0 && frame >= flashStart && frame < flashStart + 2
+ ? interpolate(frame, [flashStart, flashStart + 2], [1, 0])
+ : 0;
+
+ return (
+
+ {i > 0 && (
+
+ )}
+ {visible && (
+
+ )}
+
+ );
+ })}
+
+ );
+};
diff --git a/apps/videos/src/compositions/promo-teaser/scenes/TaglineCascadeScene.tsx b/apps/videos/src/compositions/promo-teaser/scenes/TaglineCascadeScene.tsx
new file mode 100644
index 00000000..f7b127c0
--- /dev/null
+++ b/apps/videos/src/compositions/promo-teaser/scenes/TaglineCascadeScene.tsx
@@ -0,0 +1,26 @@
+import type React from "react";
+import { AbsoluteFill } from "remotion";
+import { RotatingTaglines } from "@/components/RotatingTaglines";
+
+const TAGLINES = [
+ "No signups.",
+ "No uploads.",
+ "No limits.",
+ "Free forever.",
+ "Open source.",
+ "Fully offline.",
+];
+
+export const TaglineCascadeScene: React.FC = () => {
+ return (
+
+
+
+ );
+};