← back to pranavbhasin__pranavbhasin.com

Function bodies 28 total

All specs Real LLM only Function bodies
AboutPage function · typescript · L11-L131 (121 LOC)
src/app/about/page.tsx
export default function AboutPage() {
  return (
    <div className="pt-24 pb-16">
      <div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
        {/* Header */}
        <div className="flex flex-col md:flex-row items-center gap-10 mb-16">
          <div className="relative w-48 h-48 md:w-56 md:h-56 rounded-2xl overflow-hidden shadow-lg flex-shrink-0">
            <Image
              src="/images/headshot.jpg"
              alt="Pranav Bhasin"
              fill
              className="object-cover"
              priority
            />
          </div>
          <div>
            <p className="text-gold font-semibold text-sm uppercase tracking-widest mb-2">
              About
            </p>
            <h1 className="text-3xl md:text-4xl font-bold text-navy mb-4">
              Pranav Bhasin
            </h1>
            <p className="text-lg text-body leading-relaxed">
              AI Leadership &amp; Career Strategist helping mid-to-senior
              professionals an
AcademyPage function · typescript · L46-L146 (101 LOC)
src/app/academy/page.tsx
export default function AcademyPage() {
  return (
    <div className="pt-24 pb-16">
      <div className="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8">
        {/* Header */}
        <div className="text-center mb-16">
          <p className="text-gold font-semibold text-sm uppercase tracking-widest mb-3">
            Future Proof Academy
          </p>
          <h1 className="text-3xl md:text-5xl font-bold text-navy mb-6">
            Executive courses for the AI era
          </h1>
          <p className="text-lg text-body max-w-2xl mx-auto leading-relaxed">
            Structured programs designed for mid-to-senior professionals ready to
            take control of their career trajectory in an AI-driven world.
          </p>
        </div>

        {/* Courses */}
        <div className="space-y-12">
          {courses.map((course, i) => (
            <div
              key={i}
              className="border border-gray-200 rounded-2xl p-8 md:p-10 hover:shadow-lg transition-shadow"
 
POST function · typescript · L3-L58 (56 LOC)
src/app/api/quiz-lead/route.ts
export async function POST(req: NextRequest) {
  try {
    const body = await req.json();
    const { name, email, role, yearsOfExperience, quizId, quizName, score, tier, timestamp } = body;

    // Validate required fields
    if (!name || !email || !role || !yearsOfExperience) {
      return NextResponse.json(
        { error: "All fields are required" },
        { status: 400 }
      );
    }

    const webhookUrl = process.env.GOOGLE_SHEETS_WEBHOOK_URL;

    if (webhookUrl) {
      // Post to Google Apps Script webhook
      await fetch(webhookUrl, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          name,
          email,
          role,
          yearsOfExperience,
          quizId: quizId || "unknown",
          quizName: quizName || "Unknown Quiz",
          score,
          tier,
          timestamp: timestamp || new Date().toISOString(),
        }),
      });
    } else {
      // Fallback: log to server c
BookPage function · typescript · L9-L39 (31 LOC)
src/app/book/page.tsx
export default function BookPage() {
  return (
    <div className="pt-24 pb-16">
      <div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
        <div className="text-center mb-10">
          <p className="text-gold font-semibold text-sm uppercase tracking-widest mb-3">
            1:1 Advisory
          </p>
          <h1 className="text-3xl md:text-4xl font-bold text-navy mb-4">
            Personal Advisory Session
          </h1>
          <p className="text-lg text-body max-w-2xl mx-auto">
            A focused 60-minute session to discuss your career strategy, AI
            leadership trajectory, or any specific challenges you&apos;re facing.
          </p>
        </div>

        {/* Calendly embed */}
        <div className="rounded-2xl overflow-hidden border border-gray-200 shadow-sm">
          <iframe
            src="https://calendly.com/pranavbhasin/personal-advisory-session-with-pranav-60-mins-1-1"
            width="100%"
            height="700"
            clas
RootLayout function · typescript · L32-L52 (21 LOC)
src/app/layout.tsx
export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en">
      <head>
        <link
          href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap"
          rel="stylesheet"
        />
      </head>
      <body className="bg-white antialiased">
        <Navbar />
        <main>{children}</main>
        <Footer />
      </body>
    </html>
  );
}
NewsletterPage function · typescript · L12-L107 (96 LOC)
src/app/newsletter/page.tsx
export default async function NewsletterPage() {
  const articles = await getLatestArticles(20);

  return (
    <div className="pt-24 pb-16">
      <div className="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8">
        {/* Header */}
        <div className="text-center mb-12">
          <p className="text-gold font-semibold text-sm uppercase tracking-widest mb-3">
            Newsletter
          </p>
          <h1 className="text-3xl md:text-4xl font-bold text-navy mb-4">
            Future Proof with Pranav
          </h1>
          <p className="text-lg text-body max-w-2xl mx-auto mb-8">
            Weekly insights on AI leadership, career strategy, and navigating
            professional disruption in an AI-driven world.
          </p>

          {/* Subscribe embed */}
          <div className="max-w-md mx-auto mb-12">
            <SubscribeForm variant="light" />
          </div>
        </div>

        {/* Articles */}
        {articles.length > 0 ? (
          <div className="space-
Home function · typescript · L9-L24 (16 LOC)
src/app/page.tsx
export default async function Home() {
  const [{ longForm }, articles] = await Promise.all([
    getLatestVideos(50),
    getLatestArticles(3),
  ]);

  return (
    <>
      <Hero />
      <AboutSection />
      <AcademySection />
      <ContentHub articles={articles} videos={longForm.slice(0, 3)} />
      <QuizCTA />
    </>
  );
}
Source: Repobility analyzer · https://repobility.com
getResult function · typescript · L101-L161 (61 LOC)
src/app/tools/career-assessment/CareerQuiz.tsx
function getResult(score: number): Result {
  const percentage = (score / (questions.length * 4)) * 100;

  if (percentage >= 80) {
    return {
      tier: "Future-Proof Leader",
      title: "You're ahead of the curve",
      description:
        "You have a strong foundation for thriving in the AI era. Your combination of technical adaptability, cross-domain expertise, and strategic positioning puts you in an excellent position to lead.",
      recommendations: [
        "Consider the AI Leadership course to formalize and amplify your advantage",
        "Help others in your organization navigate the AI transition",
        "Build thought leadership around your unique cross-domain expertise",
        "Subscribe to the newsletter for cutting-edge frameworks",
      ],
      color: "text-green-600",
    };
  } else if (percentage >= 60) {
    return {
      tier: "Strong Foundation",
      title: "You're on the right track",
      description:
        "You have solid fundamentals but 
CareerQuiz function · typescript · L173-L500 (328 LOC)
src/app/tools/career-assessment/CareerQuiz.tsx
export default function CareerQuiz() {
  const [currentQuestion, setCurrentQuestion] = useState(0);
  const [answers, setAnswers] = useState<Record<string, number>>({});
  const [showLeadCapture, setShowLeadCapture] = useState(false);
  const [showResults, setShowResults] = useState(false);
  const [leadInfo, setLeadInfo] = useState<LeadInfo>({
    name: "",
    email: "",
    role: "",
    yearsOfExperience: "",
  });
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [leadError, setLeadError] = useState("");

  const totalScore = Object.values(answers).reduce((a, b) => a + b, 0);
  const result = getResult(totalScore);
  const progress = ((currentQuestion) / questions.length) * 100;

  function handleAnswer(questionId: string, score: number) {
    const newAnswers = { ...answers, [questionId]: score };
    setAnswers(newAnswers);

    if (currentQuestion < questions.length - 1) {
      setTimeout(() => setCurrentQuestion(currentQuestion + 1), 300);
    } else {
      
handleAnswer function · typescript · L191-L200 (10 LOC)
src/app/tools/career-assessment/CareerQuiz.tsx
  function handleAnswer(questionId: string, score: number) {
    const newAnswers = { ...answers, [questionId]: score };
    setAnswers(newAnswers);

    if (currentQuestion < questions.length - 1) {
      setTimeout(() => setCurrentQuestion(currentQuestion + 1), 300);
    } else {
      setTimeout(() => setShowLeadCapture(true), 300);
    }
  }
handleLeadSubmit function · typescript · L202-L229 (28 LOC)
src/app/tools/career-assessment/CareerQuiz.tsx
  async function handleLeadSubmit(e: React.FormEvent) {
    e.preventDefault();
    setLeadError("");
    setIsSubmitting(true);

    try {
      const scorePercentage = Math.round((totalScore / (questions.length * 4)) * 100);
      const res = await fetch("/api/quiz-lead", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          ...leadInfo,
          quizId: QUIZ_ID,
          quizName: QUIZ_NAME,
          score: scorePercentage,
          tier: getResult(totalScore).tier,
          timestamp: new Date().toISOString(),
        }),
      });

      if (!res.ok) throw new Error("Failed to submit");
      setShowResults(true);
    } catch {
      setLeadError("Something went wrong. Please try again.");
    } finally {
      setIsSubmitting(false);
    }
  }
restart function · typescript · L231-L238 (8 LOC)
src/app/tools/career-assessment/CareerQuiz.tsx
  function restart() {
    setCurrentQuestion(0);
    setAnswers({});
    setShowLeadCapture(false);
    setShowResults(false);
    setLeadInfo({ name: "", email: "", role: "", yearsOfExperience: "" });
    setLeadError("");
  }
CareerAssessmentPage function · typescript · L10-L18 (9 LOC)
src/app/tools/career-assessment/page.tsx
export default function CareerAssessmentPage() {
  return (
    <div className="pt-24 pb-16">
      <div className="max-w-3xl mx-auto px-4 sm:px-6 lg:px-8">
        <CareerQuiz />
      </div>
    </div>
  );
}
VideoCard function · typescript · L12-L43 (32 LOC)
src/app/videos/page.tsx
function VideoCard({ video }: { video: YouTubeVideo }) {
  return (
    <a
      href={`https://www.youtube.com/watch?v=${video.videoId}`}
      target="_blank"
      rel="noopener noreferrer"
      className="group rounded-xl overflow-hidden border border-gray-200 hover:border-gold/30 hover:shadow-lg transition-all"
    >
      <div className="relative aspect-video">
        <Image
          src={video.thumbnail}
          alt={video.title}
          fill
          className="object-cover"
        />
        <div className="absolute inset-0 bg-black/20 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity">
          <div className="bg-red-600 rounded-full p-3">
            <svg className="w-6 h-6 text-white" fill="currentColor" viewBox="0 0 24 24">
              <path d="M8 5v14l11-7z" />
            </svg>
          </div>
        </div>
      </div>
      <div className="p-4">
        <p className="text-xs text-body/60 mb-1">{video.date}</p>
        
VideosPage function · typescript · L45-L114 (70 LOC)
src/app/videos/page.tsx
export default async function VideosPage() {
  const { longForm } = await getLatestVideos(50);

  return (
    <div className="pt-24 pb-16">
      <div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
        {/* Header */}
        <div className="text-center mb-12">
          <p className="text-gold font-semibold text-sm uppercase tracking-widest mb-3">
            Videos
          </p>
          <h1 className="text-3xl md:text-4xl font-bold text-navy mb-4">
            Future Proof with Pranav
          </h1>
          <p className="text-lg text-body max-w-2xl mx-auto mb-6">
            In-depth videos breaking down AI trends, career frameworks, and
            leadership strategies for the modern professional.
          </p>
          <a
            href="https://www.youtube.com/@future-proof-by-pranav?sub_confirmation=1"
            target="_blank"
            rel="noopener noreferrer"
            className="inline-flex items-center gap-2 bg-red-600 hover:bg-red-700 text-white f
Repobility's GitHub App fixes findings like these · https://github.com/apps/repobility-bot
AboutSection function · typescript · L3-L42 (40 LOC)
src/components/AboutSection.tsx
export default function AboutSection() {
  return (
    <section id="about" className="py-16 md:py-24 bg-off-white">
      <div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
        <div className="max-w-3xl mx-auto text-center">
          <p className="text-gold font-semibold text-sm uppercase tracking-widest mb-3">
            About
          </p>
          <h2 className="text-3xl md:text-4xl font-bold text-navy mb-6">
            The intersection of AI and career strategy
          </h2>
          <p className="text-body text-lg leading-relaxed mb-6">
            I help professionals navigate the most significant career disruption
            of our generation. With deep expertise across AI, product strategy,
            and executive leadership, I equip mid-to-senior professionals with
            the frameworks, skills, and confidence to not just survive — but lead
            — in an AI-transformed world.
          </p>
          <p className="text-body text-lg leading-rela
AcademySection function · typescript · L24-L72 (49 LOC)
src/components/AcademySection.tsx
export default function AcademySection() {
  return (
    <section id="academy" className="py-16 md:py-24 bg-white">
      <div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
        <div className="text-center mb-12">
          <p className="text-gold font-semibold text-sm uppercase tracking-widest mb-3">
            Future Proof Academy
          </p>
          <h2 className="text-3xl md:text-4xl font-bold text-navy mb-4">
            Executive courses for the AI era
          </h2>
          <p className="text-body text-lg max-w-2xl mx-auto">
            Structured programs designed for mid-to-senior professionals ready
            to take control of their career trajectory.
          </p>
        </div>

        <div className="grid grid-cols-1 md:grid-cols-2 gap-8 max-w-4xl mx-auto">
          {courses.map((course, i) => (
            <div
              key={i}
              className="border border-gray-200 rounded-xl p-8 hover:border-gold/50 hover:shadow-lg transition-all g
ContentHub function · typescript · L11-L128 (118 LOC)
src/components/ContentHub.tsx
export default function ContentHub({ articles, videos }: ContentHubProps) {
  return (
    <section id="content" className="py-16 md:py-24 bg-off-white">
      <div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
        <div className="text-center mb-12">
          <p className="text-gold font-semibold text-sm uppercase tracking-widest mb-3">
            Insights
          </p>
          <h2 className="text-3xl md:text-4xl font-bold text-navy mb-4">
            Latest thinking on AI &amp; careers
          </h2>
        </div>

        <div className="grid grid-cols-1 lg:grid-cols-2 gap-12">
          {/* Newsletter / Substack */}
          <div>
            <div className="flex items-center gap-3 mb-6">
              <svg className="w-6 h-6 text-gold" fill="currentColor" viewBox="0 0 24 24">
                <path d="M22.539 8.242H1.46V5.406h21.08v2.836zM1.46 10.812V24l9.56-5.26L20.54 24V10.812H1.46zM22.54 0H1.46v2.836h21.08V0z" />
              </svg>
              <h3 className=
Footer function · typescript · L4-L128 (125 LOC)
src/components/Footer.tsx
export default function Footer() {
  return (
    <footer className="bg-navy text-white">
      {/* Newsletter signup */}
      <div className="border-b border-white/10">
        <div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
          <div className="max-w-xl mx-auto text-center">
            <h3 className="text-2xl font-bold text-white mb-2">
              Future Proof Your Career
            </h3>
            <p className="text-white/70 mb-6">
              Weekly insights on AI leadership, career strategy, and staying
              ahead in an AI-driven world.
            </p>
            <SubscribeForm variant="dark" />
          </div>
        </div>
      </div>

      {/* Footer links */}
      <div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8 py-10">
        <div className="grid grid-cols-1 md:grid-cols-3 gap-8">
          {/* Brand */}
          <div>
            <h4 className="font-bold text-lg text-white mb-3">Pranav Bhasin</h4>
            <p className
Hero function · typescript · L4-L58 (55 LOC)
src/components/Hero.tsx
export default function Hero() {
  return (
    <section className="pt-24 pb-16 md:pt-32 md:pb-24 bg-white">
      <div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
        <div className="flex flex-col md:flex-row items-center gap-10 md:gap-16">
          {/* Text */}
          <div className="flex-1 text-center md:text-left">
            <p className="text-gold font-semibold text-sm uppercase tracking-widest mb-3">
              AI Leadership &amp; Career Strategy
            </p>
            <h1 className="text-4xl md:text-5xl lg:text-6xl font-extrabold text-navy leading-tight mb-6">
              Build a career that thrives in the age of AI
            </h1>
            <p className="text-lg text-body max-w-xl mb-8 leading-relaxed">
              Helping mid-to-senior professionals and executives build
              defensible careers and lead effectively in an AI-driven world.
            </p>
            <div className="flex flex-col sm:flex-row gap-4 justify-center md:jus
Navbar function · typescript · L15-L112 (98 LOC)
src/components/Navbar.tsx
export default function Navbar() {
  const [mobileOpen, setMobileOpen] = useState(false);

  return (
    <nav className="fixed top-0 left-0 right-0 z-50 bg-white/95 backdrop-blur-sm border-b border-gray-100">
      <div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
        <div className="flex items-center justify-between h-16">
          {/* Logo */}
          <Link href="/" className="flex items-center gap-3">
            <Image
              src="/images/logo.jpg"
              alt="Pranav Bhasin"
              width={36}
              height={36}
              className="rounded"
            />
            <span className="text-navy font-bold text-lg tracking-tight">
              Future Proof <span className="font-normal text-body">by Pranav Bhasin</span>
            </span>
          </Link>

          {/* Desktop Nav */}
          <div className="hidden md:flex items-center gap-8">
            {navLinks.map((link) => (
              <Link
                key={link.label}
QuizCTA function · typescript · L4-L44 (41 LOC)
src/components/QuizCTA.tsx
export default function QuizCTA() {
  return (
    <section className="py-16 md:py-24 bg-white">
      <div className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8">
        <div className="bg-navy rounded-2xl p-8 md:p-12 flex flex-col md:flex-row items-center justify-center gap-8 md:gap-12">
          {/* Mascot */}
          <div className="flex-shrink-0 flex items-center">
            <div className="w-32 h-32 md:w-44 md:h-44 relative">
              <Image
                src="/images/mascot.jpg"
                alt="Future Proof mascot"
                fill
                className="object-contain"
              />
            </div>
          </div>

          {/* Content */}
          <div className="flex-1 text-center md:text-left">
            <h2 className="text-2xl md:text-3xl font-bold mb-3" style={{ color: '#D4A33C' }}>
              How Future-Proof Is Your Career?
            </h2>
            <p className="text-white/70 text-lg mb-6 max-w-lg">
              Take the free car
SubscribeForm function · typescript · L9-L88 (80 LOC)
src/components/SubscribeForm.tsx
export default function SubscribeForm({ variant = "light" }: SubscribeFormProps) {
  const [email, setEmail] = useState("");
  const [status, setStatus] = useState<"idle" | "loading" | "success" | "error">("idle");

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    if (!email) return;

    setStatus("loading");

    try {
      const res = await fetch("https://neuralnugget.substack.com/api/v1/free?noRedirect=true", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          first_url: "https://neuralnugget.substack.com/embed",
          first_referrer: "https://pranavbhasin.com",
          current_url: "https://neuralnugget.substack.com/embed",
          current_referrer: "https://pranavbhasin.com",
          referral_code: "",
          source: "embed",
          email,
        }),
      });

      if (res.ok) {
        setStatus("success");
        setEmail("");
      } else {
        setSta
Methodology: Repobility · https://repobility.com/research/state-of-ai-code-2026/
handleSubmit function · typescript · L13-L43 (31 LOC)
src/components/SubscribeForm.tsx
  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    if (!email) return;

    setStatus("loading");

    try {
      const res = await fetch("https://neuralnugget.substack.com/api/v1/free?noRedirect=true", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          first_url: "https://neuralnugget.substack.com/embed",
          first_referrer: "https://pranavbhasin.com",
          current_url: "https://neuralnugget.substack.com/embed",
          current_referrer: "https://pranavbhasin.com",
          referral_code: "",
          source: "embed",
          email,
        }),
      });

      if (res.ok) {
        setStatus("success");
        setEmail("");
      } else {
        setStatus("error");
      }
    } catch {
      setStatus("error");
    }
  }
getLatestArticles function · typescript · L8-L34 (27 LOC)
src/lib/substack.ts
export async function getLatestArticles(count = 3): Promise<SubstackArticle[]> {
  try {
    const res = await fetch("https://neuralnugget.substack.com/api/v1/posts?limit=" + count, {
      next: { revalidate: 3600 },
    });

    if (!res.ok) {
      // Fallback: try RSS
      return getArticlesFromRSS(count);
    }

    const posts = await res.json();

    return posts.map((post: Record<string, unknown>) => ({
      title: post.title as string,
      url: post.canonical_url as string || `https://neuralnugget.substack.com/p/${post.slug}`,
      date: new Date(post.post_date as string).toLocaleDateString("en-US", {
        year: "numeric",
        month: "short",
        day: "numeric",
      }),
      excerpt: (post.subtitle as string) || (post.description as string) || "",
    }));
  } catch {
    return getArticlesFromRSS(count);
  }
}
getArticlesFromRSS function · typescript · L36-L77 (42 LOC)
src/lib/substack.ts
async function getArticlesFromRSS(count: number): Promise<SubstackArticle[]> {
  try {
    const res = await fetch("https://neuralnugget.substack.com/feed", {
      next: { revalidate: 3600 },
    });
    const xml = await res.text();

    const articles: SubstackArticle[] = [];
    const itemRegex = /<item>([\s\S]*?)<\/item>/g;
    let match;

    while ((match = itemRegex.exec(xml)) !== null && articles.length < count) {
      const item = match[1];
      const title = item.match(/<title><!\[CDATA\[(.*?)\]\]><\/title>/)?.[1] ||
        item.match(/<title>(.*?)<\/title>/)?.[1] || "";
      const link = item.match(/<link>(.*?)<\/link>/)?.[1] || "";
      const pubDate = item.match(/<pubDate>(.*?)<\/pubDate>/)?.[1] || "";
      const desc = item.match(/<description><!\[CDATA\[(.*?)\]\]><\/description>/)?.[1] ||
        item.match(/<description>(.*?)<\/description>/)?.[1] || "";

      // Strip HTML from description
      const excerpt = desc.replace(/<[^>]*>/g, "").slice(0, 160);

     
parseDuration function · typescript · L16-L23 (8 LOC)
src/lib/youtube.ts
function parseDuration(iso: string): number {
  const match = iso.match(/PT(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?/);
  if (!match) return 0;
  const h = parseInt(match[1] || "0", 10);
  const m = parseInt(match[2] || "0", 10);
  const s = parseInt(match[3] || "0", 10);
  return h * 3600 + m * 60 + s;
}
getLatestVideos function · typescript · L25-L111 (87 LOC)
src/lib/youtube.ts
export async function getLatestVideos(count = 50): Promise<YouTubeVideos> {
  const apiKey = process.env.YOUTUBE_API_KEY;
  const channelHandle = process.env.YOUTUBE_CHANNEL_HANDLE || "@future-proof-by-pranav";

  if (!apiKey) return { longForm: [], shorts: [] };

  try {
    // Resolve channel handle to channel ID
    const channelRes = await fetch(
      `https://www.googleapis.com/youtube/v3/channels?part=contentDetails&forHandle=${channelHandle}&key=${apiKey}`,
      { next: { revalidate: 3600 } }
    );
    const channelData = await channelRes.json();

    if (!channelData.items?.length) return { longForm: [], shorts: [] };

    const uploadsPlaylistId =
      channelData.items[0].contentDetails.relatedPlaylists.uploads;

    // Fetch latest videos from uploads playlist
    const videosRes = await fetch(
      `https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&playlistId=${uploadsPlaylistId}&maxResults=${count}&key=${apiKey}`,
      { next: { revalidate: 3600 } }