From 73a4e22d5d2cdecc195697fd9ddb23dd6fdaccd3 Mon Sep 17 00:00:00 2001 From: urjitc <135136842+urjitc@users.noreply.github.com> Date: Sun, 19 Apr 2026 04:44:09 +0000 Subject: [PATCH] Add public SSR landing page at root to fix Google OAuth verification --- src/app/page.tsx | 296 ++++++++++++++++++++++- src/components/landing/LandingFooter.tsx | 90 +++++++ src/components/landing/LandingHeader.tsx | 53 ++++ src/proxy.ts | 26 +- 4 files changed, 452 insertions(+), 13 deletions(-) create mode 100644 src/components/landing/LandingFooter.tsx create mode 100644 src/components/landing/LandingHeader.tsx diff --git a/src/app/page.tsx b/src/app/page.tsx index 27dffd50..7ac037ad 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,5 +1,295 @@ -import { redirect } from "next/navigation"; +import type { Metadata } from "next"; +import Link from "next/link"; +import { ThinkExLogo } from "@/components/ui/thinkex-logo"; +import { LandingFooter } from "@/components/landing/LandingFooter"; +import { LandingHeader } from "@/components/landing/LandingHeader"; -export default function Page() { - redirect("/home"); +export const metadata: Metadata = { + title: "ThinkEx – Your Docs, Media, and AI in One Place", + description: + "ThinkEx is a visual thinking workspace where your PDFs, videos, notes, and AI conversations come together on a single canvas. Study, research, and synthesize information without switching between tabs.", + alternates: { canonical: "https://thinkex.app/" }, + openGraph: { + title: "ThinkEx – Your Docs, Media, and AI in One Place", + description: + "A visual thinking workspace for PDFs, videos, notes, and AI chat. Made for students, researchers, and anyone who learns deeply.", + url: "https://thinkex.app/", + siteName: "ThinkEx", + images: [ + { url: "/opengraph.png", width: 1200, height: 630, alt: "ThinkEx" }, + ], + type: "website", + }, + twitter: { + card: "summary_large_image", + title: "ThinkEx – Your Docs, Media, and AI in One Place", + description: + "A visual thinking workspace for PDFs, videos, notes, and AI chat.", + images: ["/opengraph.png"], + }, +}; + +export default function LandingPage() { + return ( +
+ +
+
+
+
+ +

+ ThinkEx +

+
+

+ Your Docs, Media, and AI in One Place +

+

+ ThinkEx is a visual thinking workspace where PDFs, videos, notes, + and AI conversations come together on a single canvas. Study, + research, and synthesize information without switching between + endless tabs and windows. +

+
+ + Get started free + + + Sign in + +
+

+ Free to try · No credit card required · Open source +

+
+
+ +
+
+

+ What is ThinkEx? +

+
+

+ Today's apps and AI split what should be a single, fluid + process. AI reasoning happens in isolated chat threads, while + your information is scattered across tabs, windows, and browser + bookmarks. +

+

+ ThinkEx brings it all together. Imagine a large desk where you + can spread out textbooks, lecture slides, research papers, + YouTube videos, lecture recordings, and your own notes + side-by-side. You look across everything, connect ideas, compare + sources, and ask questions. ThinkEx is that desk, in your + browser, with AI that works alongside you on exactly the context + you choose. +

+

+ It's made for students preparing for exams, researchers + synthesizing literature, writers organizing sources, and anyone + who learns better when they can see and arrange everything at + once. +

+
+
+
+ +
+
+

+ Everything you need, on one canvas +

+

+ ThinkEx combines sources, notes, and AI into a single workspace + you control. +

+
+ + + + + + + + + +
+
+
+ +
+
+

+ How ThinkEx works +

+

+ Four steps from scattered sources to compounded knowledge. +

+
+ + + + +
+
+
+ +
+
+

+ Who uses ThinkEx +

+
+ + + +
+
+
+ +
+
+

+ Start thinking in ThinkEx +

+

+ Free to try in your browser. Upload a document or paste a link to + get started in under a minute. +

+
+ + Create your free account + + + Read our Privacy Policy + +
+
+
+
+ +
+ ); +} + +function FeatureCard({ + title, + description, +}: { + title: string; + description: string; +}) { + return ( +
+

{title}

+

+ {description} +

+
+ ); +} + +function Step({ + number, + title, + description, +}: { + number: string; + title: string; + description: string; +}) { + return ( +
+
+ {number} +
+

{title}

+

+ {description} +

+
+ ); +} + +function UseCase({ + title, + description, +}: { + title: string; + description: string; +}) { + return ( +
+

{title}

+

+ {description} +

+
+ ); } diff --git a/src/components/landing/LandingFooter.tsx b/src/components/landing/LandingFooter.tsx new file mode 100644 index 00000000..e500baac --- /dev/null +++ b/src/components/landing/LandingFooter.tsx @@ -0,0 +1,90 @@ +import Link from "next/link"; +import { ThinkExLogo } from "@/components/ui/thinkex-logo"; + +export function LandingFooter() { + const currentYear = new Date().getFullYear(); + + return ( + + ); +} diff --git a/src/components/landing/LandingHeader.tsx b/src/components/landing/LandingHeader.tsx new file mode 100644 index 00000000..cff126e4 --- /dev/null +++ b/src/components/landing/LandingHeader.tsx @@ -0,0 +1,53 @@ +import Link from "next/link"; +import { ThinkExLogo } from "@/components/ui/thinkex-logo"; + +export function LandingHeader() { + return ( +
+
+ + + ThinkEx + + +
+
+ ); +} diff --git a/src/proxy.ts b/src/proxy.ts index b20fa659..0531bd2c 100644 --- a/src/proxy.ts +++ b/src/proxy.ts @@ -3,31 +3,38 @@ import { getSessionCookie } from "better-auth/cookies"; /** * Next.js Proxy for Better Auth - * + * * NOTE: getSessionCookie() only checks for cookie existence, not validation. * This is intentional for performance - we don't want to block requests with * database/API calls in proxy. - * + * * Actual security validation happens in: * - API routes using auth.api.getSession() * - Server components using auth.api.getSession() - * + * * This proxy is only for optimistic redirects based on cookie presence. */ export async function proxy(request: NextRequest) { const sessionCookie = getSessionCookie(request); const { pathname } = request.nextUrl; - // Send all users from root to home - session handling happens there + // Root: send logged-in users to the dashboard, but serve the public + // marketing landing page to unauthenticated visitors so search engines + // and OAuth reviewers can see app info, features, and privacy links + // without going through any login or anonymous session creation. if (pathname === "/") { - return NextResponse.redirect(new URL("/home", request.url)); + if (sessionCookie) { + return NextResponse.redirect(new URL("/home", request.url)); + } + return NextResponse.next(); } // Redirect authenticated users away from sign-in page only // Note: /sign-up is NOT blocked because anonymous users (who have a session cookie) // need to be able to reach the sign-up page to create a real account if (sessionCookie && pathname === "/sign-in") { - const redirectUrl = request.nextUrl.searchParams.get('redirect_url') || '/home'; + const redirectUrl = + request.nextUrl.searchParams.get("redirect_url") || "/home"; return NextResponse.redirect(new URL(redirectUrl, request.url)); } @@ -41,9 +48,8 @@ export async function proxy(request: NextRequest) { export const config = { matcher: [ // Skip Next.js internals and all static files, unless found in search params - '/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)', + "/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)", // Always run for API routes - '/(api|trpc)(.*)', + "/(api|trpc)(.*)", ], -} - +};