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.
+
+ );
}
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)(.*)",
],
-}
-
+};