From 1c0dc38d4e20118410bf6ee23295e5a482b57d0e Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 20 Jan 2026 12:49:28 +0000 Subject: [PATCH] fix(web): bypass Clerk middleware for sitemap.xml and robots.txt Add explicit NextResponse.next() bypass for sitemap and robots paths to prevent Clerk from interfering with these static routes. --- apps/web/src/middleware.ts | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/apps/web/src/middleware.ts b/apps/web/src/middleware.ts index f6f82e5..810ec12 100644 --- a/apps/web/src/middleware.ts +++ b/apps/web/src/middleware.ts @@ -1,12 +1,21 @@ import { clerkMiddleware, createRouteMatcher } from "@clerk/nextjs/server"; +import { NextResponse } from "next/server"; // Whitelist approach: ONLY dashboard requires auth // Landing page, docs, pricing, etc. - all public -const isProtectedRoute = createRouteMatcher([ - "/dashboard(.*)", -]); +const isProtectedRoute = createRouteMatcher(["/dashboard(.*)"]); + +// Paths that should completely bypass Clerk +const BYPASS_PATHS = ["/sitemap.xml", "/robots.txt"]; export default clerkMiddleware(async (auth, req) => { + const pathname = req.nextUrl.pathname; + + // Bypass Clerk entirely for sitemap and robots + if (BYPASS_PATHS.includes(pathname)) { + return NextResponse.next(); + } + if (isProtectedRoute(req)) { await auth.protect(); } @@ -14,8 +23,8 @@ export default clerkMiddleware(async (auth, req) => { export const config = { matcher: [ - // Skip Next.js internals and static files (including xml for sitemap, txt for robots) - "/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest|xml|txt)).*)", + // Skip Next.js internals and static files + "/((?!_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)(.*)", ],