diff --git a/videos/remotion-demo/src/Root.tsx b/videos/remotion-demo/src/Root.tsx index b73f9fc..1f25334 100644 --- a/videos/remotion-demo/src/Root.tsx +++ b/videos/remotion-demo/src/Root.tsx @@ -3,6 +3,7 @@ import { Composition } from "remotion"; import { SquareMCPLinkedIn } from "./SquareMCPLinkedIn"; import { SquareMCPHeroLoop } from "./SquareMCPHeroLoop"; import { YCAppVideo } from "./YCAppVideo"; +import { SquareMCPBrokerDemo } from "./SquareMCPBrokerDemo"; import { SquareMCPTikTokCTA, SquareMCPTikTokDemo, @@ -105,6 +106,14 @@ export const RemotionRoot = () => { width={1920} height={1080} /> + ); }; diff --git a/videos/remotion-demo/src/SquareMCPBrokerDemo.tsx b/videos/remotion-demo/src/SquareMCPBrokerDemo.tsx new file mode 100644 index 0000000..c839d71 --- /dev/null +++ b/videos/remotion-demo/src/SquareMCPBrokerDemo.tsx @@ -0,0 +1,279 @@ +import { AbsoluteFill, interpolate, spring, useCurrentFrame, useVideoConfig } from "remotion"; +import { COLORS, FONT, SPRING_CFG, SPRING_SOFT } from "./styles"; + + + +// ─── SCENE TIMINGS ─────────────────────────────────────────────────── +const SCENES = { + title: { start: 0, duration: 3 }, // 0:00–0:03 + emailIn: { start: 3, duration: 10 }, // 0:03–0:13 + rateBlast:{ start: 13, duration: 10 }, // 0:13–0:23 + whatsapp: { start: 23, duration: 8 }, // 0:23–0:31 + facebook: { start: 31, duration: 8 }, // 0:31–0:39 + outro: { start: 39, duration: 6 }, // 0:39–0:45 +} as const; + +// ─── HELPERS ───────────────────────────────────────────────────────── +function useSceneProgress(sceneStart: number, sceneDuration: number) { + const frame = useCurrentFrame(); + const { fps } = useVideoConfig(); + const startFrame = sceneStart * fps; + const endFrame = (sceneStart + sceneDuration) * fps; + const progress = interpolate(frame, [startFrame, endFrame], [0, 1], { + extrapolateLeft: "clamp", + extrapolateRight: "clamp", + }); + const fadeIn = interpolate(frame, [startFrame, startFrame + 0.5 * fps], [0, 1], { + extrapolateLeft: "clamp", + extrapolateRight: "clamp", + }); + const fadeOut = interpolate(frame, [endFrame - 0.5 * fps, endFrame], [1, 0], { + extrapolateLeft: "clamp", + extrapolateRight: "clamp", + }); + return { progress, opacity: fadeIn * fadeOut, startFrame, endFrame }; +} + +// ─── TITLE CARD ────────────────────────────────────────────────────── +const TitleScene = () => { + const frame = useCurrentFrame(); + const { fps } = useVideoConfig(); + const { opacity } = useSceneProgress(SCENES.title.start, SCENES.title.duration); + + const titleY = spring({ frame: frame - SCENES.title.start * fps, fps, config: SPRING_CFG, from: 40, to: 0 }); + const subtitleY = spring({ frame: frame - SCENES.title.start * fps, fps, config: SPRING_CFG, from: 30, to: 0, delay: 5 }); + + return ( + +
+
+ A Day in the Life +
+
+ + Mortgage Broker +
+
+ Powered by SquareMCP +
+ + ); +}; + +// ─── EMAIL INBOX SCENE ─────────────────────────────────────────────── +const EmailInboxScene = () => { + const frame = useCurrentFrame(); + const { fps } = useVideoConfig(); + const { opacity } = useSceneProgress(SCENES.emailIn.start, SCENES.emailIn.duration); + const localFrame = frame - SCENES.emailIn.start * fps; + + const emails = [ + { from: "Sarah J.", subject: "Pre-approval letter?", time: "8:14 AM", unread: true }, + { from: "Mike T.", subject: "Rate lock expiration", time: "8:22 AM", unread: true }, + { from: "Linda R.", subject: "Refinance question", time: "8:31 AM", unread: true }, + { from: "David K.", subject: "Closing docs status", time: "8:45 AM", unread: true }, + { from: "Jessica M.", subject: "Down payment help", time: "9:02 AM", unread: true }, + ]; + + return ( + +
+ 8:00 AM — 47 unread emails +
+
+ {/* Inbox */} +
+ {emails.map((e, i) => { + const y = spring({ frame: localFrame, fps, config: SPRING_SOFT, from: 30, to: 0, delay: i * 4 }); + const op = interpolate(localFrame, [i * 4, i * 4 + 8], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp" }); + return ( +
+
+
{e.from}
+
{e.subject}
+
{e.time}
+
+ ); + })} +
+ {/* SquareMCP overlay */} +
+
+
■ SquareMCP
+
+ Reading 47 emails...{"\n"} + Drafting responses...{"\n"} + ✓ 5 replies queued +
+
+
+
+ + ); +}; + +// ─── RATE BLAST SCENE ──────────────────────────────────────────────── +const RateBlastScene = () => { + const frame = useCurrentFrame(); + const { fps } = useVideoConfig(); + const { opacity } = useSceneProgress(SCENES.rateBlast.start, SCENES.rateBlast.duration); + const localFrame = frame - SCENES.rateBlast.start * fps; + + const count = Math.floor(interpolate(localFrame, [2 * fps, 6 * fps], [0, 200], { extrapolateLeft: "clamp", extrapolateRight: "clamp" })); + const barWidth = interpolate(localFrame, [2 * fps, 6 * fps], [0, 100], { extrapolateLeft: "clamp", extrapolateRight: "clamp" }); + + return ( + +
+ 10:30 AM — Daily Rate Update +
+
+
API Call
+
+ POST /api/email/send{"\n"} + to: 200 prospects{"\n"} + subject: "Today's Rates - May 14"{"\n"} + body: rate_table + personalized_note +
+
+
+
+
+
+ {count}/200 +
+
+
+ {count >= 200 ? ✓ All 200 prospects notified in 3.2s : "Sending..."} +
+
+ + ); +}; + +// ─── WHATSAPP SCENE ────────────────────────────────────────────────── +const WhatsAppScene = () => { + const frame = useCurrentFrame(); + const { fps } = useVideoConfig(); + const { opacity } = useSceneProgress(SCENES.whatsapp.start, SCENES.whatsapp.duration); + const localFrame = frame - SCENES.whatsapp.start * fps; + + const msgOp = interpolate(localFrame, [1 * fps, 2 * fps], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp" }); + const replyOp = interpolate(localFrame, [3 * fps, 4 * fps], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp" }); + + return ( + +
+ 2:15 PM — Client on WhatsApp +
+
+ {/* Client message */} +
+
+
Hey Alex, did rates go up today?
+
2:15 PM
+
+
+ {/* SquareMCP reply */} +
+
+
Hi! Yes, 30-year fixed ticked up to 6.875%. Want me to lock you in?
+
2:15 PM · SquareMCP
+
+
+ {/* Label */} +
+ + ■ Auto-responded via SquareMCP + +
+
+
+ ); +}; + +// ─── FACEBOOK SCENE ────────────────────────────────────────────────── +const FacebookScene = () => { + const frame = useCurrentFrame(); + const { fps } = useVideoConfig(); + const { opacity } = useSceneProgress(SCENES.facebook.start, SCENES.facebook.duration); + const localFrame = frame - SCENES.facebook.start * fps; + + const commentOp = interpolate(localFrame, [1 * fps, 2 * fps], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp" }); + const replyOp = interpolate(localFrame, [3 * fps, 4 * fps], [0, 1], { extrapolateLeft: "clamp", extrapolateRight: "clamp" }); + + return ( + +
+ 4:00 PM — Facebook Page +
+
+ {/* Post */} +
+
F
+
+
Ferrari Lending
+
2 hrs ago
+
+
+
+ 🏠 Thinking about buying your first home? DM us for a free rate quote — no credit pull required. +
+ {/* Comment */} +
+
+
+
+
Carlos V.
+
Do you work with FHA loans?
+
+
+
+ {/* Reply */} +
+
+
F
+
+
Ferrari Lending
+
Yes! FHA, VA, and conventional. Send us a DM and we'll get you pre-qualified today. 🎯
+
■ Replied via SquareMCP
+
+
+
+
+ + ); +}; + +// ─── OUTRO ─────────────────────────────────────────────────────────── +const OutroScene = () => { + const { opacity } = useSceneProgress(SCENES.outro.start, SCENES.outro.duration); + const localFrame = useCurrentFrame() - SCENES.outro.start * 30; + + const scale = spring({ frame: localFrame, fps: 30, config: SPRING_CFG, from: 0.9, to: 1 }); + + return ( + +
+
+
SquareMCP
+
One API. Every Platform.
+
squaremcp.com
+
+
+ ); +}; + +// ─── MAIN COMPOSITION ──────────────────────────────────────────────── +export const SquareMCPBrokerDemo = () => { + return ( + + + + + + + + + ); +};