// middleware.ts import { NextResponse } from "next/server"; import type { NextRequest } from "next/server"; const LAUNCH_ONLY_ROOT = process.env.NEXT_PUBLIC_LAUNCH_ONLY_ROOT === "true"; // ✅ Forever allow list (always reachable even during launch-only mode) const ALWAYS_ALLOW = new Set([ "/", "/favicon.ico", "/robots.txt", "/sitemap.xml", ]); // Match common public/static file extensions so middleware never blocks them const PUBLIC_FILE = /\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js|map|txt|xml|json|woff|woff2|ttf|eot)$/i; export function middleware(req: NextRequest) { if (!LAUNCH_ONLY_ROOT) return NextResponse.next(); const { pathname } = req.nextUrl; // ✅ Always allow Next internals + static assets (public/ and _next/) if ( pathname.startsWith("/_next") || pathname.startsWith("/favicon") || pathname === "/robots.txt" || pathname === "/sitemap.xml" || PUBLIC_FILE.test(pathname) ) { return NextResponse.next(); } // ✅ Allow the root + a few public files if (ALWAYS_ALLOW.has(pathname)) return NextResponse.next(); // 🚫 Everything else: hide it return NextResponse.rewrite(new URL("/404", req.url)); } export const config = { // Run middleware on everything *except* Next internals and obvious static files. // This keeps launch gating from ever breaking your logo/images/fonts/etc. matcher: [ "/((?!_next/static|_next/image|favicon.ico|robots.txt|sitemap.xml|.*\\.(?:svg|png|jpg|jpeg|gif|webp|ico|css|js|map|txt|xml|json|woff|woff2|ttf|eot)).*)", ], };