diff --git a/apps/web/app/(landing)/home/CTAButtons.tsx b/apps/web/app/(landing)/home/CTAButtons.tsx index d9805d78bc..89919ff55d 100644 --- a/apps/web/app/(landing)/home/CTAButtons.tsx +++ b/apps/web/app/(landing)/home/CTAButtons.tsx @@ -2,6 +2,7 @@ import { Button } from "@/components/Button"; import { usePostHog } from "posthog-js/react"; +import { landingPageAnalytics } from "@/hooks/useAnalytics"; export function CTAButtons() { const posthog = usePostHog(); @@ -12,9 +13,7 @@ export function CTAButtons() { size="2xl" color="blue" link={{ href: "/login" }} - onClick={() => { - posthog.capture("Clicked Get Started"); - }} + onClick={() => landingPageAnalytics.getStartedClicked(posthog)} > Get Started for Free @@ -24,9 +23,7 @@ export function CTAButtons() { size="2xl" color="transparent" link={{ href: "/sales", target: "_blank" }} - onClick={() => { - posthog.capture("Clicked talk to sales"); - }} + onClick={() => landingPageAnalytics.talkToSalesClicked(posthog)} > Talk to sales diff --git a/apps/web/app/(landing)/home/Header.tsx b/apps/web/app/(landing)/home/Header.tsx index 0b979bb58e..5507d5085c 100644 --- a/apps/web/app/(landing)/home/Header.tsx +++ b/apps/web/app/(landing)/home/Header.tsx @@ -27,6 +27,7 @@ import { navigationMenuTriggerStyle, } from "@/components/ui/navigation-menu"; import { EXTENSION_URL } from "@/utils/config"; +import { landingPageAnalytics } from "@/hooks/useAnalytics"; const navigation = [ { name: "Enterprise", href: "/enterprise" }, @@ -171,7 +172,7 @@ export function Header({ className }: { className?: string }) { { - posthog.capture("Clicked Log In", { position: "top-nav" }); + landingPageAnalytics.logInClicked(posthog, "top-nav"); setMobileMenuOpen(false); }} > @@ -182,7 +183,7 @@ export function Header({ className }: { className?: string }) { { - posthog.capture("Clicked Sign Up", { position: "top-nav" }); + landingPageAnalytics.signUpClicked(posthog, "top-nav"); setMobileMenuOpen(false); }} > @@ -268,7 +269,7 @@ export function Header({ className }: { className?: string }) { href="/login" className="-mx-3 block rounded-lg px-3 py-2.5 text-base font-semibold leading-7 text-gray-900 hover:bg-gray-50" onClick={() => { - posthog.capture("Clicked Log In", { position: "top-nav" }); + landingPageAnalytics.logInClicked(posthog, "top-nav"); setMobileMenuOpen(false); }} > diff --git a/apps/web/app/(landing)/layout.tsx b/apps/web/app/(landing)/layout.tsx index 5ab1303112..b9cb279550 100644 --- a/apps/web/app/(landing)/layout.tsx +++ b/apps/web/app/(landing)/layout.tsx @@ -1,6 +1,6 @@ import { LemonScript } from "@/utils/scripts/lemon"; -export default async function AppLayout({ +export default async function LandingLayout({ children, }: { children: React.ReactNode; diff --git a/apps/web/app/(landing)/new-landing/page.tsx b/apps/web/app/(landing)/new-landing/page.tsx deleted file mode 100644 index b2eb4b34e1..0000000000 --- a/apps/web/app/(landing)/new-landing/page.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import type { Metadata } from "next"; -import { BasicLayout } from "@/components/new-landing/common/BasicLayout"; -import { FAQs } from "@/components/new-landing/sections/FAQs"; -import { Testimonials } from "@/components/new-landing/sections/Testimonials"; -import { Hero } from "@/components/new-landing/sections/Hero"; -import { Pricing } from "@/components/new-landing/sections/Pricing"; -import { Awards } from "@/components/new-landing/sections/Awards"; -import { BuyBackTime } from "@/components/new-landing/sections/BuyBackTime"; -import { EverythingElseSection } from "@/components/new-landing/sections/EverythingElseSection"; -import { StartedInMinutes } from "@/components/new-landing/sections/StartedInMinutes"; -import { BulkUnsubscribe } from "@/components/new-landing/sections/BulkUnsubscribe"; -import { OrganizedInbox } from "@/components/new-landing/sections/OrganizedInbox"; -import { PreWrittenDrafts } from "@/components/new-landing/sections/PreWrittenDrafts"; - -export const metadata: Metadata = { alternates: { canonical: "/" } }; - -export default function NewLanding() { - return ( - - - - - - - - - - - - - - ); -} diff --git a/apps/web/app/(landing)/old-landing/page.tsx b/apps/web/app/(landing)/old-landing/page.tsx new file mode 100644 index 0000000000..7e0dd3e696 --- /dev/null +++ b/apps/web/app/(landing)/old-landing/page.tsx @@ -0,0 +1,25 @@ +import type { Metadata } from "next"; +import { HeroHome } from "@/app/(landing)/home/Hero"; +import { BasicLayout } from "@/components/layouts/BasicLayout"; +import { FeaturesHome } from "@/app/(landing)/home/Features"; +import { Privacy } from "@/app/(landing)/home/Privacy"; +import { Testimonials } from "@/app/(landing)/home/Testimonials"; +import { PricingLazy } from "@/app/(app)/premium/PricingLazy"; +import { FAQs } from "@/app/(landing)/home/FAQs"; +import { CTA } from "@/app/(landing)/home/CTA"; + +export const metadata: Metadata = { alternates: { canonical: "/" } }; + +export default function Home() { + return ( + + + + + + + + + + ); +} diff --git a/apps/web/app/(landing)/page.tsx b/apps/web/app/(landing)/page.tsx index 7e0dd3e696..77ad636e89 100644 --- a/apps/web/app/(landing)/page.tsx +++ b/apps/web/app/(landing)/page.tsx @@ -1,25 +1,33 @@ import type { Metadata } from "next"; -import { HeroHome } from "@/app/(landing)/home/Hero"; -import { BasicLayout } from "@/components/layouts/BasicLayout"; -import { FeaturesHome } from "@/app/(landing)/home/Features"; -import { Privacy } from "@/app/(landing)/home/Privacy"; -import { Testimonials } from "@/app/(landing)/home/Testimonials"; -import { PricingLazy } from "@/app/(app)/premium/PricingLazy"; -import { FAQs } from "@/app/(landing)/home/FAQs"; -import { CTA } from "@/app/(landing)/home/CTA"; +import { BasicLayout } from "@/components/new-landing/common/BasicLayout"; +import { FAQs } from "@/components/new-landing/sections/FAQs"; +import { Testimonials } from "@/components/new-landing/sections/Testimonials"; +import { Hero } from "@/components/new-landing/sections/Hero"; +import { Pricing } from "@/components/new-landing/sections/Pricing"; +import { Awards } from "@/components/new-landing/sections/Awards"; +import { FinalCTA } from "@/components/new-landing/sections/FinalCTA"; +import { EverythingElseSection } from "@/components/new-landing/sections/EverythingElseSection"; +import { StartedInMinutes } from "@/components/new-landing/sections/StartedInMinutes"; +import { BulkUnsubscribe } from "@/components/new-landing/sections/BulkUnsubscribe"; +import { OrganizedInbox } from "@/components/new-landing/sections/OrganizedInbox"; +import { PreWrittenDrafts } from "@/components/new-landing/sections/PreWrittenDrafts"; export const metadata: Metadata = { alternates: { canonical: "/" } }; -export default function Home() { +export default function NewLanding() { return ( - - + + + + + + + + - - + - ); } diff --git a/apps/web/components/HeroVideoDialog.tsx b/apps/web/components/HeroVideoDialog.tsx index a14cfa578c..3d1ec6c38e 100644 --- a/apps/web/components/HeroVideoDialog.tsx +++ b/apps/web/components/HeroVideoDialog.tsx @@ -1,6 +1,5 @@ "use client"; -import { useCallback } from "react"; import Image from "next/image"; import { Play } from "lucide-react"; import { cn } from "@/utils"; @@ -11,6 +10,7 @@ import { DialogTitle, DialogTrigger, } from "@/components/ui/dialog"; +import { landingPageAnalytics } from "@/hooks/useAnalytics"; interface HeroVideoProps { videoSrc: string; @@ -27,17 +27,13 @@ export default function HeroVideoDialog({ }: HeroVideoProps) { const posthog = usePostHog(); - const handleOpenVideo = useCallback(() => { - posthog.capture("Landing Page Video Clicked"); - }, [posthog]); - return (
- {includeSalesButton ? ( - + - ) : null} + +
); } diff --git a/apps/web/components/new-landing/HeaderLinks.tsx b/apps/web/components/new-landing/HeaderLinks.tsx index 8499b27050..0d5cd3ef93 100644 --- a/apps/web/components/new-landing/HeaderLinks.tsx +++ b/apps/web/components/new-landing/HeaderLinks.tsx @@ -19,16 +19,10 @@ import { NavigationMenuTrigger, navigationMenuTriggerStyle, } from "@/components/ui/navigation-menu"; -import { EXTENSION_URL } from "@/utils/config"; const navigation = [ { name: "Enterprise", href: "/enterprise" }, { name: "Open Source", href: "/github", target: "_blank" as const }, - { - name: "Extension", - href: EXTENSION_URL, - target: "_blank" as const, - }, { name: "Pricing", href: "/#pricing" }, ]; diff --git a/apps/web/components/new-landing/LiquidGlassButton.tsx b/apps/web/components/new-landing/LiquidGlassButton.tsx index 2b1c5403d1..1dc1e04e55 100644 --- a/apps/web/components/new-landing/LiquidGlassButton.tsx +++ b/apps/web/components/new-landing/LiquidGlassButton.tsx @@ -36,7 +36,7 @@ export function LiquidGlassButton({ "inset 2px 2px 1px 0 rgba(255, 255, 255, 0.5), inset -1px -1px 1px 1px rgba(255, 255, 255, 0.5)", }} /> -
+
{children}
diff --git a/apps/web/components/new-landing/common/BasicLayout.tsx b/apps/web/components/new-landing/common/BasicLayout.tsx index f32700d1b6..7733e3c02e 100644 --- a/apps/web/components/new-landing/common/BasicLayout.tsx +++ b/apps/web/components/new-landing/common/BasicLayout.tsx @@ -6,7 +6,7 @@ const LAYOUT_CLASSNAME = "max-w-6xl mx-auto px-6 lg:px-8 xl:px-0"; export function BasicLayout(props: { children: React.ReactNode }) { return ( -
+
{props.children}
diff --git a/apps/web/components/new-landing/common/Button.tsx b/apps/web/components/new-landing/common/Button.tsx index 74c8a70dc6..7057f0cd83 100644 --- a/apps/web/components/new-landing/common/Button.tsx +++ b/apps/web/components/new-landing/common/Button.tsx @@ -1,14 +1,15 @@ +import { Slot } from "@radix-ui/react-slot"; import { cva, cx } from "class-variance-authority"; export type ButtonVariant = "primary" | "secondary" | "secondary-two"; -interface ButtonProps { +interface ButtonProps extends React.ButtonHTMLAttributes { children: React.ReactNode; variant?: ButtonVariant; className?: string; size?: "md" | "lg" | "xl"; - icon?: React.ReactNode; auto?: boolean; + asChild?: boolean; } export function Button({ @@ -17,12 +18,16 @@ export function Button({ variant = "primary", className, size = "md", - icon, + asChild = false, + ...props }: ButtonProps) { - const hasIcon = !!icon; + const Comp = asChild ? Slot : "button"; + const type = props.type ?? "button"; + const buttonVariants = cva( [ "rounded-[13px] font-geist font-medium transition-all will-change-transform", + "flex items-center justify-center gap-2", variant === "primary" ? "" : "hover:scale-[1.04]", ], { @@ -36,16 +41,13 @@ export function Button({ secondary: "bg-white hover:bg-gray-50 border border-gray-100 hover:border-gray-200 text-gray-800", "secondary-two": - "bg-white hover:bg-gray-50 border border-gray-100 hover:border-gray-200 text-gray-500 shadow-[0px_2px_16px_0px_#00000008] hover:shadow-[0px_2px_16px_0px_#00000015]", + "bg-white hover:bg-gray-50 border border-gray-100 hover:border-gray-200 text-gray-500 shadow-[0px_2px_16px_0px_#00000008] hover:shadow-[0px_2px_16px_0px_#00000015] [&>svg]:text-[#AEAAA8]", }, size: { md: "text-sm py-2 px-4", lg: "text-sm py-[10.5px] px-[18px]", xl: "text-[16px] py-[11.7px] px-[22px]", }, - hasIcon: { - true: "flex items-center justify-center gap-2", - }, auto: { true: "w-full", }, @@ -53,16 +55,7 @@ export function Button({ }, ); - const buttonIconVariants = cva("", { - variants: { - variant: { - primary: "", - secondary: "", - "secondary-two": "text-[#AEAAA8]", - }, - }, - }); - + // For primary variant with gradient border wrapper if (variant === "primary") { return (
- + {asChild ? ( + children + ) : ( + {children} + )} +
); } + // For secondary variants - simpler, no wrapper return ( - + ); } diff --git a/apps/web/components/new-landing/common/Section.tsx b/apps/web/components/new-landing/common/Section.tsx index 085e357ddf..bab98eb078 100644 --- a/apps/web/components/new-landing/common/Section.tsx +++ b/apps/web/components/new-landing/common/Section.tsx @@ -3,11 +3,12 @@ import { cx } from "class-variance-authority"; interface SectionProps { children: React.ReactNode; className?: string; + id?: string; } -export function Section({ children, className }: SectionProps) { +export function Section({ children, className, id }: SectionProps) { return ( -
+
{children}
); diff --git a/apps/web/components/new-landing/sections/BuyBackTime.tsx b/apps/web/components/new-landing/sections/FinalCTA.tsx similarity index 81% rename from apps/web/components/new-landing/sections/BuyBackTime.tsx rename to apps/web/components/new-landing/sections/FinalCTA.tsx index f36d440a7e..12ae28e97c 100644 --- a/apps/web/components/new-landing/sections/BuyBackTime.tsx +++ b/apps/web/components/new-landing/sections/FinalCTA.tsx @@ -8,7 +8,7 @@ import { SectionSubtitle, } from "@/components/new-landing/common/Typography"; -export function BuyBackTime() { +export function FinalCTA() { return (
- +
diff --git a/apps/web/components/new-landing/sections/Header.tsx b/apps/web/components/new-landing/sections/Header.tsx index ad0e1db723..84f01e8e09 100644 --- a/apps/web/components/new-landing/sections/Header.tsx +++ b/apps/web/components/new-landing/sections/Header.tsx @@ -1,13 +1,20 @@ +"use client"; + +import Link from "next/link"; +import { usePostHog } from "posthog-js/react"; import { cn } from "@/utils"; import { Logo } from "@/components/new-landing/common/Logo"; import { Button } from "@/components/new-landing/common/Button"; import { HeaderLinks } from "@/components/new-landing/HeaderLinks"; +import { landingPageAnalytics } from "@/hooks/useAnalytics"; interface HeaderProps { className: string; } export function Header({ className }: HeaderProps) { + const posthog = usePostHog(); + return (
- - + +
); diff --git a/apps/web/components/new-landing/sections/Hero.tsx b/apps/web/components/new-landing/sections/Hero.tsx index bcffe70759..4b2d886138 100644 --- a/apps/web/components/new-landing/sections/Hero.tsx +++ b/apps/web/components/new-landing/sections/Hero.tsx @@ -1,6 +1,7 @@ "use client"; import Image from "next/image"; +import { usePostHog } from "posthog-js/react"; import { Gmail } from "@/components/new-landing/icons/Gmail"; import { Outlook } from "@/components/new-landing/icons/Outlook"; import { @@ -25,6 +26,7 @@ import { BlurFade } from "@/components/new-landing/common/BlurFade"; import { WordReveal } from "@/components/new-landing/common/WordReveal"; import { userCount } from "@/utils/config"; import { UnicornScene } from "@/components/new-landing/UnicornScene"; +import { landingPageAnalytics } from "@/hooks/useAnalytics"; export function Hero() { return ( @@ -77,16 +79,21 @@ export function Hero() { } export function HeroVideoPlayer() { + const posthog = usePostHog(); + return (
- + landingPageAnalytics.videoClicked(posthog)} + > - + Video player