From 539b3e43108b3a5f33cc3707e50c419cd82d9afd Mon Sep 17 00:00:00 2001 From: Urjit Chakraborty <135136842+urjitc@users.noreply.github.com> Date: Fri, 16 Jan 2026 17:04:55 -0500 Subject: [PATCH 01/11] refactor: extract shared BackgroundCard component from Hero and FinalCTA --- src/components/landing/BackgroundCard.tsx | 49 +++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 src/components/landing/BackgroundCard.tsx diff --git a/src/components/landing/BackgroundCard.tsx b/src/components/landing/BackgroundCard.tsx new file mode 100644 index 00000000..88b83ce3 --- /dev/null +++ b/src/components/landing/BackgroundCard.tsx @@ -0,0 +1,49 @@ +import type { CardColor } from "@/lib/workspace-state/colors"; +import { getCardColorCSS } from "@/lib/workspace-state/colors"; + +export interface BackgroundCardData { + top: string; + left: string; + width: string; + height: string; + color: CardColor; + rotation: number; +} + +interface BackgroundCardProps { + card: BackgroundCardData; + isMobileOnly?: boolean; +} + +export function BackgroundCard({ card, isMobileOnly = false }: BackgroundCardProps) { + return ( +
+ {/* Card content placeholder */} +
+
+
+
+
+
+
+
+ ); +} + +// Random card colors for background +export const cardColors: CardColor[] = [ + "#8B5CF6", "#3B82F6", "#10B981", "#F59E0B", "#EF4444", + "#EC4899", "#06B6D4", "#84CC16", "#F97316", "#6366F1", +]; From 2f37990e8a163894d68295546606a2daaf324230 Mon Sep 17 00:00:00 2001 From: Urjit Chakraborty <135136842+urjitc@users.noreply.github.com> Date: Fri, 16 Jan 2026 17:04:59 -0500 Subject: [PATCH 02/11] refactor: use shared BackgroundCard component in Hero and FinalCTA; add prefetch to Get Started links --- src/components/landing/FinalCTA.tsx | 45 ++------------------------ src/components/landing/Hero.tsx | 50 ++++++----------------------- 2 files changed, 12 insertions(+), 83 deletions(-) diff --git a/src/components/landing/FinalCTA.tsx b/src/components/landing/FinalCTA.tsx index 5929f2cf..129cd31c 100644 --- a/src/components/landing/FinalCTA.tsx +++ b/src/components/landing/FinalCTA.tsx @@ -2,17 +2,10 @@ import Link from "next/link"; import { Button } from "@/components/ui/button"; -import { getCardColorCSS } from "@/lib/workspace-state/colors"; -import type { CardColor } from "@/lib/workspace-state/colors"; - -// Random card colors for background -const cardColors: CardColor[] = [ - "#8B5CF6", "#3B82F6", "#10B981", "#F59E0B", "#EF4444", - "#EC4899", "#06B6D4", "#84CC16", "#F97316", "#6366F1", -]; +import { BackgroundCard, cardColors, type BackgroundCardData } from "./BackgroundCard"; // Random card positions and sizes (static - no parallax) -const backgroundCards = [ +const backgroundCards: BackgroundCardData[] = [ { top: "15%", left: "10%", width: "180px", height: "140px", color: cardColors[0], rotation: -3 }, { top: "30%", left: "75%", width: "200px", height: "160px", color: cardColors[1], rotation: 2 }, { top: "60%", left: "15%", width: "160px", height: "120px", color: cardColors[2], rotation: -2 }, @@ -20,38 +13,6 @@ const backgroundCards = [ { top: "20%", left: "50%", width: "170px", height: "130px", color: cardColors[4], rotation: 1 }, ]; -interface BackgroundCardProps { - card: typeof backgroundCards[0]; - isMobileOnly?: boolean; -} - -function BackgroundCard({ card, isMobileOnly = false }: BackgroundCardProps) { - return ( -
- {/* Card content placeholder */} -
-
-
-
-
-
-
-
- ); -} - export function FinalCTA() { return (
- +
@@ -160,6 +126,8 @@ export function Hero() { src="/demo.png" alt="ThinkEx Demo" fill + priority + sizes="(max-width: 768px) 0vw, 80vw" className="object-cover" />
From 55c6ae92b73590f4f8fcd544b49dc9b4f717c040 Mon Sep 17 00:00:00 2001 From: Urjit Chakraborty <135136842+urjitc@users.noreply.github.com> Date: Fri, 16 Jan 2026 17:05:04 -0500 Subject: [PATCH 03/11] feat: add lazy loading and sizes attributes to below-fold images; remove priority from footer logo --- src/components/landing/Footer.tsx | 2 +- src/components/landing/FourWays.tsx | 15 +++++++-------- src/components/landing/ThreeSteps.tsx | 2 ++ 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/components/landing/Footer.tsx b/src/components/landing/Footer.tsx index 6d9f8f07..a7b6607b 100644 --- a/src/components/landing/Footer.tsx +++ b/src/components/landing/Footer.tsx @@ -17,8 +17,8 @@ export function Footer() { alt="ThinkEx Logo" width={24} height={24} + loading="lazy" className="object-contain" - priority />
ThinkEx diff --git a/src/components/landing/FourWays.tsx b/src/components/landing/FourWays.tsx index 0a291a13..d61071b0 100644 --- a/src/components/landing/FourWays.tsx +++ b/src/components/landing/FourWays.tsx @@ -95,14 +95,9 @@ export function FourWays() { className={`space-y-4 md:space-y-6 ${way.imageSide === "left" ? "md:col-start-2" : "" }`} > -
- - {index + 1} - -

- {way.title} -

-
+

+ {way.title} +

    {way.bullets.map((bullet, bulletIndex) => (
  • {bullet}
  • @@ -121,6 +116,8 @@ export function FourWays() { src={way.image} alt={way.title} fill + loading="lazy" + sizes="(max-width: 768px) 100vw, 0vw" className="object-cover" style={ way.image === "/attachments.png" @@ -140,6 +137,8 @@ export function FourWays() { alt={way.title} width={800} height={600} + loading="lazy" + sizes="(max-width: 768px) 0vw, 50vw" className="w-full h-full object-cover" style={ way.image === "/attachments.png" diff --git a/src/components/landing/ThreeSteps.tsx b/src/components/landing/ThreeSteps.tsx index 89ab9a79..a20c729d 100644 --- a/src/components/landing/ThreeSteps.tsx +++ b/src/components/landing/ThreeSteps.tsx @@ -71,6 +71,8 @@ export function ThreeSteps() { src={step.image} alt={step.title} fill + loading="lazy" + sizes="(max-width: 768px) 100vw, 33vw" className="object-cover" style={step.id === "step-2" ? { objectPosition: "left center" } : undefined} /> From cfcc33a199fd01c510de9008b9feeada5b7981e0 Mon Sep 17 00:00:00 2001 From: Urjit Chakraborty <135136842+urjitc@users.noreply.github.com> Date: Fri, 16 Jan 2026 17:05:08 -0500 Subject: [PATCH 04/11] feat: add prefetch to critical navigation links in Navbar and Pricing --- src/components/landing/Navbar.tsx | 436 ++++++++++++++--------------- src/components/landing/Pricing.tsx | 2 +- 2 files changed, 219 insertions(+), 219 deletions(-) diff --git a/src/components/landing/Navbar.tsx b/src/components/landing/Navbar.tsx index 295779cc..de8b5d31 100644 --- a/src/components/landing/Navbar.tsx +++ b/src/components/landing/Navbar.tsx @@ -34,11 +34,11 @@ export function Navbar() { handleScroll(); // Check on mount return () => window.removeEventListener("scroll", handleScroll); }, []); - + const userName = session?.user?.name || session?.user?.email || "User"; const userEmail = session?.user?.email || ""; const userImage = session?.user?.image || undefined; - + const getInitials = (name: string) => { if (name === "User") return "U"; return name @@ -63,238 +63,238 @@ export function Navbar() { transition={{ duration: 0.5 }} className="sticky top-0 z-50" > -
    - - {/* Logo/Brand */} - -
    - ThinkEx Logo -
    - ThinkEx - +
    + + {/* Logo/Brand */} + +
    + ThinkEx Logo +
    + ThinkEx + - {/* Desktop Navigation - Centered */} - - - {/* Desktop CTA */} -
    - {!isPending && !session && ( - <> + {/* Desktop Navigation - Centered */} +
    + {navLinks.map((link) => ( - - - { + e.preventDefault(); + const element = document.querySelector(link.href); + if (element) { + element.scrollIntoView({ behavior: 'smooth', block: 'start' }); + } + }} className="text-sm font-normal text-foreground/70 transition-colors hover:text-foreground cursor-pointer" > - Login - - -
    + + {/* Desktop CTA */} +
    + {!isPending && !session && ( + <> + - Get Started - - - - )} - {!isPending && session && ( - <> - - - - - - - - -
    -

    {userName}

    - {userEmail && ( -

    {userEmail}

    - )} -
    - - setShowAccountModal(true)} - className="cursor-pointer" + Login + + + + + + )} + {!isPending && session && ( + <> + +
    - - {/* Mobile menu dropdown */} -
    - - - - - - {navLinks.map((link) => ( - { - e.preventDefault(); - const element = document.querySelector(link.href); - if (element) { - element.scrollIntoView({ behavior: 'smooth', block: 'start' }); - } - }} - className="cursor-pointer" - > - {link.label} - - ))} - {!isPending && !session && ( - <> - - - - - - - - + + + + + + +
    +

    {userName}

    + {userEmail && ( +

    {userEmail}

    + )} +
    + + setShowAccountModal(true)} className="cursor-pointer" > - Login - - - - posthog.capture('navbar-get-started-clicked', { location: 'mobile' })} - className="cursor-pointer" - > - Get Started - - - - )} - {!isPending && session && ( - <> - - - posthog.capture('navbar-dashboard-clicked', { location: 'mobile' })} + Account Settings + + + signOut()} className="cursor-pointer" > - Dashboard - - - -
    -

    {userName}

    - {userEmail && ( -

    {userEmail}

    - )} -
    - - setShowAccountModal(true)} - className="cursor-pointer" - > - Account Settings - - + Sign Out +
    +
    +
    + + )} +
    + + {/* Mobile menu dropdown */} +
    + + + + + + {navLinks.map((link) => ( signOut()} + key={link.href} + onClick={(e) => { + e.preventDefault(); + const element = document.querySelector(link.href); + if (element) { + element.scrollIntoView({ behavior: 'smooth', block: 'start' }); + } + }} className="cursor-pointer" > - Sign Out + {link.label} - - )} - - -
    - -
    - - - + ))} + {!isPending && !session && ( + <> + + + + + + + + + Login + + + + posthog.capture('navbar-get-started-clicked', { location: 'mobile' })} + className="cursor-pointer" + > + Get Started + + + + )} + {!isPending && session && ( + <> + + + posthog.capture('navbar-dashboard-clicked', { location: 'mobile' })} + className="cursor-pointer" + > + Dashboard + + + +
    +

    {userName}

    + {userEmail && ( +

    {userEmail}

    + )} +
    + + setShowAccountModal(true)} + className="cursor-pointer" + > + Account Settings + + + signOut()} + className="cursor-pointer" + > + Sign Out + + + )} + + +
    +
    +
    + + + ); } diff --git a/src/components/landing/Pricing.tsx b/src/components/landing/Pricing.tsx index 62c80b70..caa34630 100644 --- a/src/components/landing/Pricing.tsx +++ b/src/components/landing/Pricing.tsx @@ -158,7 +158,7 @@ export function Pricing() { ))}
- + - + + )} {!isPending && session && ( <> - - - + + - + +
diff --git a/src/components/landing/Hero.tsx b/src/components/landing/Hero.tsx index 4b9da625..f35b5ab0 100644 --- a/src/components/landing/Hero.tsx +++ b/src/components/landing/Hero.tsx @@ -90,14 +90,15 @@ export function Hero() { {/* Get Started Button - Above Video */}
- - - + +
{/* Mobile Demo Image - Only visible on mobile */} diff --git a/src/components/landing/Pricing.tsx b/src/components/landing/Pricing.tsx index caa34630..7aa0a469 100644 --- a/src/components/landing/Pricing.tsx +++ b/src/components/landing/Pricing.tsx @@ -158,18 +158,19 @@ export function Pricing() { ))} - - - + +
))}
From a5e873b900a7ff349bffdd9676652547b5e7ac81 Mon Sep 17 00:00:00 2001 From: Urjit Chakraborty <135136842+urjitc@users.noreply.github.com> Date: Fri, 16 Jan 2026 17:19:57 -0500 Subject: [PATCH 11/11] style: increase Hero demo image width to max-w-6xl to match other sections --- src/components/landing/Hero.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/landing/Hero.tsx b/src/components/landing/Hero.tsx index f35b5ab0..895f5794 100644 --- a/src/components/landing/Hero.tsx +++ b/src/components/landing/Hero.tsx @@ -119,7 +119,7 @@ export function Hero() { {/* Desktop Demo Image - Hidden on mobile */}
-
+