feat(remotion): YC application video template + talking points
- Add YCAppVideo Remotion composition (1920x1080, 60s) - 3s intro card with founder name + company - 55s video placeholder with branded frame + lower thirds - 2s outro card with logo + tagline - Update Root.tsx with new composition - Add YC_APPLICATION_TALKING_POINTS.md with bullet points and recording tips per YC instructions
This commit is contained in:
52
product/YC_APPLICATION_TALKING_POINTS.md
Normal file
52
product/YC_APPLICATION_TALKING_POINTS.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# Y Combinator Application Video — Talking Points
|
||||
|
||||
> **Rules from YC:** 1 minute. Founders talking. No script — use bullet points only. Talk like you're explaining to a friend.
|
||||
|
||||
---
|
||||
|
||||
## Your Bullet Points (≈60 seconds)
|
||||
|
||||
**[0:00–0:10] Who you are**
|
||||
- "Hey, I'm Garfield Heron, solo founder of SquareMCP."
|
||||
- "I'm a builder who's been in the trenches of API integrations for years."
|
||||
|
||||
**[0:10–0:25] The problem**
|
||||
- "Every company now needs to post to TikTok, Instagram, LinkedIn, Twitter, WhatsApp, Telegram, Discord, Facebook, and email."
|
||||
- "Right now that's 9 different APIs, 9 different auth flows, 9 different docs, 9 different failure modes."
|
||||
- "Engineers spend weeks wiring this up. Then it breaks when TikTok changes their API or Meta deprecates a permission."
|
||||
|
||||
**[0:25–0:40] What SquareMCP is**
|
||||
- "SquareMCP is one API that connects to all of them."
|
||||
- "You authenticate once per platform through our dashboard, then call one endpoint: `publish_post` or `send_message`."
|
||||
- "We handle the tokens, the rate limits, the retries, the API changes."
|
||||
- "It's built on the Model Context Protocol — an open standard — so AI agents can use it too."
|
||||
|
||||
**[0:40–0:52] Traction / proof**
|
||||
- "We've got the full TikTok sandbox working, Facebook Graph API, and SMTP/email."
|
||||
- "We're live at squaremcp.com with per-user credential storage, usage tracking, and invoice-based billing."
|
||||
- "TikTok app review is in progress."
|
||||
|
||||
**[0:52–1:00] Why you, why now**
|
||||
- "I lived this pain. I'm the exact person to fix it."
|
||||
- "AI agents need to post to social too — and they need a standard way to do it. MCP is that standard."
|
||||
- "We're building the infrastructure layer that every AI-native company will need."
|
||||
|
||||
---
|
||||
|
||||
## Recording Tips
|
||||
|
||||
1. **Use your phone or laptop webcam** — 1080p is plenty. Good lighting matters more than camera quality.
|
||||
2. **Look at the lens, not the screen.** It feels like eye contact.
|
||||
3. **Don't memorize.** Glance at these bullet points, then talk naturally. Stumbling is fine — YC prefers real over polished.
|
||||
4. **One continuous take.** No cuts, no B-roll, no music. Just you talking.
|
||||
5. **Background:** clean wall, or a desk with a monitor showing your product. Nothing distracting.
|
||||
|
||||
## After Recording
|
||||
|
||||
1. Export your raw video as `my-recording.mp4` (1920×1080 ideally)
|
||||
2. Replace the placeholder in `YCAppVideo.tsx` with an `<OffthreadVideo>` component pointing to your file
|
||||
3. Re-render: `npx remotion render YCAppVideo out/final-yc-video.mp4`
|
||||
|
||||
---
|
||||
|
||||
*Good luck!* 🚀
|
||||
@@ -2,6 +2,7 @@ import "./index.css";
|
||||
import { Composition } from "remotion";
|
||||
import { SquareMCPLinkedIn } from "./SquareMCPLinkedIn";
|
||||
import { SquareMCPHeroLoop } from "./SquareMCPHeroLoop";
|
||||
import { YCAppVideo } from "./YCAppVideo";
|
||||
import {
|
||||
SquareMCPTikTokCTA,
|
||||
SquareMCPTikTokDemo,
|
||||
@@ -78,6 +79,14 @@ export const RemotionRoot = () => {
|
||||
width={1080}
|
||||
height={1920}
|
||||
/>
|
||||
<Composition
|
||||
id="YCAppVideo"
|
||||
component={YCAppVideo}
|
||||
durationInFrames={60 * 30}
|
||||
fps={30}
|
||||
width={1920}
|
||||
height={1080}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
335
videos/remotion-demo/src/YCAppVideo.tsx
Normal file
335
videos/remotion-demo/src/YCAppVideo.tsx
Normal file
@@ -0,0 +1,335 @@
|
||||
import { AbsoluteFill, interpolate, spring, useCurrentFrame, useVideoConfig } from "remotion";
|
||||
import { COLORS, FONT, SPRING_CFG } from "./styles";
|
||||
|
||||
// ─── CONFIG ──────────────────────────────────────────────────────────
|
||||
const INTRO_DURATION = 3; // seconds
|
||||
const OUTRO_DURATION = 2; // seconds
|
||||
const TOTAL_DURATION = 60; // seconds (YC wants ~1 min)
|
||||
|
||||
// ─── INTRO CARD ──────────────────────────────────────────────────────
|
||||
const IntroCard = () => {
|
||||
const frame = useCurrentFrame();
|
||||
const { fps } = useVideoConfig();
|
||||
|
||||
|
||||
const nameY = spring({
|
||||
frame,
|
||||
fps,
|
||||
config: SPRING_CFG,
|
||||
from: 60,
|
||||
to: 0,
|
||||
delay: 0,
|
||||
});
|
||||
|
||||
const companyY = spring({
|
||||
frame,
|
||||
fps,
|
||||
config: SPRING_CFG,
|
||||
from: 40,
|
||||
to: 0,
|
||||
delay: 5,
|
||||
});
|
||||
|
||||
const taglineOpacity = interpolate(
|
||||
frame,
|
||||
[1.5 * fps, 2 * fps],
|
||||
[0, 1],
|
||||
{ extrapolateLeft: "clamp", extrapolateRight: "clamp" }
|
||||
);
|
||||
|
||||
const fadeOut = interpolate(
|
||||
frame,
|
||||
[(INTRO_DURATION - 0.4) * fps, INTRO_DURATION * fps],
|
||||
[1, 0],
|
||||
{ extrapolateLeft: "clamp", extrapolateRight: "clamp" }
|
||||
);
|
||||
|
||||
return (
|
||||
<AbsoluteFill
|
||||
style={{
|
||||
background: `radial-gradient(ellipse at 50% 40%, ${COLORS.bgCard} 0%, ${COLORS.bg} 70%)`,
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
opacity: fadeOut,
|
||||
fontFamily: FONT,
|
||||
}}
|
||||
>
|
||||
{/* Accent glow */}
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
width: 400,
|
||||
height: 400,
|
||||
borderRadius: "50%",
|
||||
background: `radial-gradient(circle, ${COLORS.accentGlow} 0%, transparent 70%)`,
|
||||
top: "30%",
|
||||
left: "50%",
|
||||
transform: "translate(-50%, -50%)",
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Founder name */}
|
||||
<div
|
||||
style={{
|
||||
fontSize: 72,
|
||||
fontWeight: 800,
|
||||
color: COLORS.text,
|
||||
textAlign: "center",
|
||||
letterSpacing: "-0.02em",
|
||||
transform: `translateY(${nameY}px)`,
|
||||
textShadow: `0 0 60px ${COLORS.accentGlow}`,
|
||||
}}
|
||||
>
|
||||
Garfield Heron
|
||||
</div>
|
||||
|
||||
{/* Company name */}
|
||||
<div
|
||||
style={{
|
||||
fontSize: 40,
|
||||
fontWeight: 700,
|
||||
color: COLORS.accentLight,
|
||||
marginTop: 16,
|
||||
transform: `translateY(${companyY}px)`,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: 12,
|
||||
}}
|
||||
>
|
||||
<span style={{ color: COLORS.accent }}>■</span>
|
||||
SquareMCP
|
||||
</div>
|
||||
|
||||
{/* Subtitle */}
|
||||
<div
|
||||
style={{
|
||||
fontSize: 20,
|
||||
fontWeight: 400,
|
||||
color: COLORS.textSecondary,
|
||||
marginTop: 24,
|
||||
opacity: taglineOpacity,
|
||||
}}
|
||||
>
|
||||
Y Combinator Application
|
||||
</div>
|
||||
</AbsoluteFill>
|
||||
);
|
||||
};
|
||||
|
||||
// ─── VIDEO PLACEHOLDER (subtle frame for your recording) ─────────────
|
||||
const VideoFrame = ({ children }: { children?: React.ReactNode }) => {
|
||||
const frame = useCurrentFrame();
|
||||
const { fps } = useVideoConfig();
|
||||
|
||||
// Fade in from intro
|
||||
const fadeIn = interpolate(
|
||||
frame,
|
||||
[INTRO_DURATION * fps, (INTRO_DURATION + 0.5) * fps],
|
||||
[0, 1],
|
||||
{ extrapolateLeft: "clamp", extrapolateRight: "clamp" }
|
||||
);
|
||||
|
||||
// Fade out to outro
|
||||
const fadeOut = interpolate(
|
||||
frame,
|
||||
[(TOTAL_DURATION - OUTRO_DURATION - 0.5) * fps, (TOTAL_DURATION - OUTRO_DURATION) * fps],
|
||||
[1, 0],
|
||||
{ extrapolateLeft: "clamp", extrapolateRight: "clamp" }
|
||||
);
|
||||
|
||||
return (
|
||||
<AbsoluteFill
|
||||
style={{
|
||||
background: "#000000",
|
||||
opacity: fadeIn * fadeOut,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
>
|
||||
{/* Corner accents */}
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
inset: 20,
|
||||
border: `1px solid ${COLORS.borderBlue}`,
|
||||
borderRadius: 8,
|
||||
pointerEvents: "none",
|
||||
}}
|
||||
/>
|
||||
{/* Corner dots */}
|
||||
{[
|
||||
{ top: 16, left: 16 },
|
||||
{ top: 16, right: 16 },
|
||||
{ bottom: 16, left: 16 },
|
||||
{ bottom: 16, right: 16 },
|
||||
].map((pos, i) => (
|
||||
<div
|
||||
key={i}
|
||||
style={{
|
||||
position: "absolute",
|
||||
width: 6,
|
||||
height: 6,
|
||||
borderRadius: "50%",
|
||||
background: COLORS.accent,
|
||||
...pos,
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
|
||||
{/* Lower third - name + company */}
|
||||
<div
|
||||
style={{
|
||||
position: "absolute",
|
||||
bottom: 40,
|
||||
left: 40,
|
||||
right: 40,
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "flex-end",
|
||||
fontFamily: FONT,
|
||||
pointerEvents: "none",
|
||||
}}
|
||||
>
|
||||
<div>
|
||||
<div style={{ fontSize: 18, fontWeight: 700, color: COLORS.text }}>
|
||||
Garfield Heron
|
||||
</div>
|
||||
<div style={{ fontSize: 14, fontWeight: 400, color: COLORS.textSecondary, marginTop: 2 }}>
|
||||
Founder, SquareMCP
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ fontSize: 14, fontWeight: 600, color: COLORS.accentLight }}>
|
||||
squaremcp.com
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Placeholder text (remove when you overlay your actual video) */}
|
||||
{!children && (
|
||||
<div
|
||||
style={{
|
||||
fontFamily: FONT,
|
||||
color: COLORS.textSecondary,
|
||||
fontSize: 24,
|
||||
textAlign: "center",
|
||||
}}
|
||||
>
|
||||
<div>YOUR RECORDING GOES HERE</div>
|
||||
<div style={{ fontSize: 16, marginTop: 12, opacity: 0.6 }}>
|
||||
Record yourself talking, then overlay it in Remotion
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{children}
|
||||
</AbsoluteFill>
|
||||
);
|
||||
};
|
||||
|
||||
// ─── OUTRO CARD ──────────────────────────────────────────────────────
|
||||
const OutroCard = () => {
|
||||
const frame = useCurrentFrame();
|
||||
const { fps } = useVideoConfig();
|
||||
const outroStart = (TOTAL_DURATION - OUTRO_DURATION) * fps;
|
||||
const localFrame = frame - outroStart;
|
||||
|
||||
const scale = spring({
|
||||
frame: localFrame,
|
||||
fps,
|
||||
config: SPRING_CFG,
|
||||
from: 0.9,
|
||||
to: 1,
|
||||
});
|
||||
|
||||
const opacity = interpolate(
|
||||
localFrame,
|
||||
[0, 0.5 * fps],
|
||||
[0, 1],
|
||||
{ extrapolateLeft: "clamp", extrapolateRight: "clamp" }
|
||||
);
|
||||
|
||||
return (
|
||||
<AbsoluteFill
|
||||
style={{
|
||||
background: COLORS.bg,
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
opacity,
|
||||
transform: `scale(${scale})`,
|
||||
fontFamily: FONT,
|
||||
}}
|
||||
>
|
||||
{/* Logo mark */}
|
||||
<div
|
||||
style={{
|
||||
width: 64,
|
||||
height: 64,
|
||||
borderRadius: 16,
|
||||
background: COLORS.accent,
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
fontSize: 28,
|
||||
fontWeight: 800,
|
||||
color: "#fff",
|
||||
}}
|
||||
>
|
||||
■
|
||||
</div>
|
||||
|
||||
<div
|
||||
style={{
|
||||
fontSize: 48,
|
||||
fontWeight: 800,
|
||||
color: COLORS.text,
|
||||
marginTop: 24,
|
||||
letterSpacing: "-0.02em",
|
||||
}}
|
||||
>
|
||||
SquareMCP
|
||||
</div>
|
||||
|
||||
<div
|
||||
style={{
|
||||
fontSize: 22,
|
||||
fontWeight: 400,
|
||||
color: COLORS.textSecondary,
|
||||
marginTop: 12,
|
||||
}}
|
||||
>
|
||||
One API. Every Platform.
|
||||
</div>
|
||||
|
||||
<div
|
||||
style={{
|
||||
fontSize: 16,
|
||||
color: COLORS.accentLight,
|
||||
marginTop: 32,
|
||||
fontWeight: 600,
|
||||
}}
|
||||
>
|
||||
squaremcp.com
|
||||
</div>
|
||||
</AbsoluteFill>
|
||||
);
|
||||
};
|
||||
|
||||
// ─── MAIN COMPOSITION ────────────────────────────────────────────────
|
||||
export const YCAppVideo = () => {
|
||||
const frame = useCurrentFrame();
|
||||
const { fps } = useVideoConfig();
|
||||
|
||||
const showIntro = frame < INTRO_DURATION * fps;
|
||||
const showOutro = frame >= (TOTAL_DURATION - OUTRO_DURATION) * fps;
|
||||
|
||||
return (
|
||||
<AbsoluteFill style={{ background: "#000" }}>
|
||||
{showIntro && <IntroCard />}
|
||||
{!showIntro && !showOutro && <VideoFrame />}
|
||||
{showOutro && <OutroCard />}
|
||||
</AbsoluteFill>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user