// middleware.ts import { NextResponse, NextRequest } from "next/server"; const PUBLIC_PATHS = new Set([ "/auth/sign-in", "/auth/sign-up", // add oauth/callback endpoints here if you use them, e.g.: "/auth/callback" ]); export function middleware(req: NextRequest) { const { pathname } = req.nextUrl; const isAuthRoute = pathname.startsWith("/auth/"); const token = req.cookies.get("ma_at")?.value ?? ""; // If already authed and hitting an auth route, always go to the portal if (token && isAuthRoute) { const url = req.nextUrl.clone(); url.pathname = "/portal"; url.search = ""; return NextResponse.redirect(url); } // If not authed and path is protected → send to sign-in (no ?next=) if (!token && !isPublicPath(pathname)) { const url = req.nextUrl.clone(); url.pathname = "/auth/sign-in"; url.search = ""; // IMPORTANT: drop next so login always goes to /portal return NextResponse.redirect(url); } return NextResponse.next(); } // Helpers function isPublicPath(pathname: string): boolean { if (PUBLIC_PATHS.has(pathname)) return true; // Static assets / internals if ( pathname.startsWith("/_next/") || pathname.startsWith("/static/") || pathname.startsWith("/images/") || pathname === "/favicon.ico" || pathname === "/robots.txt" || pathname === "/sitemap.xml" ) return true; // API routes aren't gated here; each route should enforce auth as needed if (pathname.startsWith("/api/")) return true; // Everything else is protected return false; } export const config = { matcher: [ "/((?!_next/static|_next/image|favicon.ico|robots.txt|sitemap.xml|images|static).*)", ], };