Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 91 additions & 46 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,58 +1,103 @@
"use client";
import dynamic from "next/dynamic";
import type { Metadata } from "next";

// Static imports for above-the-fold components
import { Navbar } from "@/components/landing/Navbar";
import { Hero } from "@/components/landing/Hero";
import { FourWays } from "@/components/landing/FourWays";
import { ThreeSteps } from "@/components/landing/ThreeSteps";
import { Comparison } from "@/components/landing/Comparison";
import { Pricing } from "@/components/landing/Pricing";
import { FinalCTA } from "@/components/landing/FinalCTA";
import { Footer } from "@/components/landing/Footer";
import { SEO } from "@/components/seo/SEO";

// Dynamic imports for below-the-fold components
const FourWays = dynamic(
() => import("@/components/landing/FourWays").then((mod) => mod.FourWays),
{ ssr: true }
);

const ThreeSteps = dynamic(
() => import("@/components/landing/ThreeSteps").then((mod) => mod.ThreeSteps),
{ ssr: true }
);

const Comparison = dynamic(
() => import("@/components/landing/Comparison").then((mod) => mod.Comparison),
{ ssr: true }
);

const Pricing = dynamic(
() => import("@/components/landing/Pricing").then((mod) => mod.Pricing),
{ ssr: true }
);

const FinalCTA = dynamic(
() => import("@/components/landing/FinalCTA").then((mod) => mod.FinalCTA),
{ ssr: true }
);

const Footer = dynamic(
() => import("@/components/landing/Footer").then((mod) => mod.Footer),
{ ssr: true }
);

// Next.js Metadata API for SEO (replaces client-side SEO component)
export const metadata: Metadata = {
title: "ThinkEx",
description: "Study and work with information effortlessly.",
keywords: "AI workspace, productivity, collaboration, artificial intelligence, workspace tools, ThinkEx, AI assistant, creative workspace",
authors: [{ name: "ThinkEx" }],
openGraph: {
title: "ThinkEx",
description: "Study and work with information effortlessly.",
url: "https://thinkex.app",
siteName: "ThinkEx",
locale: "en_US",
type: "website",
},
twitter: {
card: "summary_large_image",
title: "ThinkEx",
description: "Study and work with information effortlessly.",
},
alternates: {
canonical: "https://thinkex.app",
},
robots: {
index: true,
follow: true,
},
};

export default function LandingPage() {
return (
<>
<SEO
title="ThinkEx"
description="Study and work with information effortlessly."
keywords="AI workspace, productivity, collaboration, artificial intelligence, workspace tools, ThinkEx, AI assistant, creative workspace"
url="https://thinkex.app"
canonical="https://thinkex.app"
/>
<div
className="relative min-h-screen bg-background"
style={{ fontFamily: 'var(--font-outfit)' }}
>
{/* Grid Background (static) */}
<div
className="relative min-h-screen bg-background"
style={{ fontFamily: 'var(--font-outfit)' }}
className="fixed top-0 left-0 right-0 bottom-0 z-0 opacity-55 pointer-events-none"
>
{/* Grid Background (static) */}
{/* Grid Pattern */}
<div
className="fixed top-0 left-0 right-0 bottom-0 z-0 opacity-55 pointer-events-none"
>
{/* Grid Pattern */}
<div
className="absolute inset-0"
style={{
backgroundImage: `
linear-gradient(to right, rgba(255, 255, 255, 0.08) 1px, transparent 1px),
linear-gradient(to bottom, rgba(255, 255, 255, 0.08) 1px, transparent 1px)
`,
backgroundSize: "50px 50px",
}}
/>
</div>

{/* Content */}
<div className="relative z-10">
<Navbar />
<Hero />
<FourWays />
<ThreeSteps />
<Comparison />
<Pricing />
<FinalCTA />
<Footer />
</div>
className="absolute inset-0"
style={{
backgroundImage: `
linear-gradient(to right, rgba(255, 255, 255, 0.08) 1px, transparent 1px),
linear-gradient(to bottom, rgba(255, 255, 255, 0.08) 1px, transparent 1px)
`,
backgroundSize: "50px 50px",
}}
/>
</div>

{/* Content */}
<div className="relative z-10">
<Navbar />
<Hero />
<FourWays />
<ThreeSteps />
<Comparison />
<Pricing />
<FinalCTA />
<Footer />
</div>
</>
</div>
);
}
49 changes: 49 additions & 0 deletions src/components/landing/BackgroundCard.tsx
Original file line number Diff line number Diff line change
@@ -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;
isDesktopOnly?: boolean;
}

export function BackgroundCard({ card, isDesktopOnly = false }: BackgroundCardProps) {
return (
<div
style={{
position: "absolute",
top: card.top,
left: card.left,
width: card.width,
height: card.height,
backgroundColor: getCardColorCSS(card.color as CardColor, 0.5),
transform: `rotate(${card.rotation}deg)`,
opacity: 0.5,
}}
className={`rounded-md border border-foreground/20 shadow-xl ${isDesktopOnly ? 'hidden md:block' : ''}`}
>
{/* Card content placeholder */}
<div className="p-3 h-full flex flex-col gap-2">
<div className="h-2 w-3/4 rounded bg-foreground/20" />
<div className="h-1.5 w-full rounded bg-foreground/15" />
<div className="h-1.5 w-5/6 rounded bg-foreground/15" />
<div className="flex-1" />
<div className="h-1 w-1/2 rounded bg-foreground/10" />
</div>
</div>
);
}

// Random card colors for background
export const cardColors: CardColor[] = [
"#8B5CF6", "#3B82F6", "#10B981", "#F59E0B", "#EF4444",
"#EC4899", "#06B6D4", "#84CC16", "#F97316", "#6366F1",
];
62 changes: 12 additions & 50 deletions src/components/landing/FinalCTA.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,56 +2,17 @@

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 },
{ top: "70%", left: "80%", width: "190px", height: "150px", color: cardColors[3], rotation: 3 },
{ 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 (
<div
style={{
position: "absolute",
top: card.top,
left: card.left,
width: card.width,
height: card.height,
backgroundColor: getCardColorCSS(card.color as CardColor, 0.5),
transform: `rotate(${card.rotation}deg)`,
opacity: 0.5,
}}
className={`rounded-md border border-foreground/20 shadow-xl ${isMobileOnly ? 'hidden md:block' : ''}`}
>
{/* Card content placeholder */}
<div className="p-3 h-full flex flex-col gap-2">
<div className="h-2 w-3/4 rounded bg-foreground/20" />
<div className="h-1.5 w-full rounded bg-foreground/15" />
<div className="h-1.5 w-5/6 rounded bg-foreground/15" />
<div className="flex-1" />
<div className="h-1 w-1/2 rounded bg-foreground/10" />
</div>
</div>
);
}

export function FinalCTA() {
return (
<section
Expand All @@ -62,12 +23,12 @@ export function FinalCTA() {
<div className="absolute inset-0 z-0 opacity-40">
{/* Static Background Cards */}
{backgroundCards.map((card, index) => {
const isMobileOnly = index >= 3;
const isDesktopOnly = index >= 3;
return (
<BackgroundCard
key={index}
card={card}
isMobileOnly={isMobileOnly}
isDesktopOnly={isDesktopOnly}
/>
);
})}
Expand Down Expand Up @@ -101,14 +62,15 @@ export function FinalCTA() {
</p>

<div className="flex justify-center pt-4">
<Link href="/guest-setup">
<Button
size="lg"
className="h-12 rounded-md bg-foreground px-8 text-base font-medium text-background transition-all hover:bg-foreground/90"
>
<Button
asChild
size="lg"
className="h-12 rounded-md bg-foreground px-8 text-base font-medium text-background transition-all hover:bg-foreground/90"
>
<Link href="/guest-setup" prefetch>
Get Started
</Button>
</Link>
</Link>
</Button>
</div>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/components/landing/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ export function Footer() {
alt="ThinkEx Logo"
width={24}
height={24}
loading="lazy"
className="object-contain"
priority
/>
</div>
<span className="text-xl font-normal text-foreground">ThinkEx</span>
Expand Down
15 changes: 7 additions & 8 deletions src/components/landing/FourWays.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,14 +95,9 @@ export function FourWays() {
className={`space-y-4 md:space-y-6 ${way.imageSide === "left" ? "md:col-start-2" : ""
}`}
>
<div className="flex items-center gap-4">
<span className="flex h-10 w-10 items-center justify-center rounded-full bg-foreground text-background text-lg font-semibold">
{index + 1}
</span>
<h3 className="text-2xl font-medium tracking-tight text-foreground sm:text-3xl">
{way.title}
</h3>
</div>
<h3 className="text-2xl font-medium tracking-tight text-foreground sm:text-3xl">
{way.title}
</h3>
<ul className="space-y-2 text-base md:text-lg leading-relaxed text-muted-foreground list-disc list-inside pl-1">
{way.bullets.map((bullet, bulletIndex) => (
<li key={bulletIndex}>{bullet}</li>
Expand All @@ -121,6 +116,8 @@ export function FourWays() {
src={way.image}
alt={way.title}
fill
loading="lazy"
sizes="100vw"
className="object-cover"
style={
way.image === "/attachments.png"
Expand All @@ -140,6 +137,8 @@ export function FourWays() {
alt={way.title}
width={800}
height={600}
loading="lazy"
sizes="50vw"
className="w-full h-full object-cover"
style={
way.image === "/attachments.png"
Expand Down
Loading