- Add YC_APPLICATION_ANSWERS.md with full Summer 2026 application draft (all fields answered, updated with mortgage broker user interview quote) - Wire OffthreadVideo into YCAppVideo.tsx for founder recording playback - Ignore .mov files and .gstack/ in .gitignore Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
360 lines
8.8 KiB
TypeScript
360 lines
8.8 KiB
TypeScript
import {
|
|
AbsoluteFill,
|
|
OffthreadVideo,
|
|
Sequence,
|
|
staticFile,
|
|
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)
|
|
const TALKING_HEAD_DURATION = TOTAL_DURATION - INTRO_DURATION - OUTRO_DURATION;
|
|
|
|
// ─── 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,
|
|
[0, 0.5 * fps],
|
|
[0, 1],
|
|
{ extrapolateLeft: "clamp", extrapolateRight: "clamp" }
|
|
);
|
|
|
|
// Fade out to outro
|
|
const fadeOut = interpolate(
|
|
frame,
|
|
[(TALKING_HEAD_DURATION - 0.5) * fps, TALKING_HEAD_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 />}
|
|
<Sequence
|
|
from={INTRO_DURATION * fps}
|
|
durationInFrames={TALKING_HEAD_DURATION * fps}
|
|
>
|
|
<VideoFrame>
|
|
<OffthreadVideo
|
|
src={staticFile("yc-founder-recording.mov")}
|
|
style={{
|
|
width: "100%",
|
|
height: "100%",
|
|
objectFit: "cover",
|
|
}}
|
|
/>
|
|
</VideoFrame>
|
|
</Sequence>
|
|
{showOutro && <OutroCard />}
|
|
</AbsoluteFill>
|
|
);
|
|
};
|