11import { clerkMiddleware , createRouteMatcher } from "@clerk/nextjs/server" ;
2- import { NextResponse } from 'next/server' ;
2+ import { NextResponse , type NextRequest } from 'next/server' ;
33
44const PLATFORMS = new Set ( [ 'github' , 'gitlab' , 'bitbucket' ] ) ;
55
66// Reserved paths that should NOT be treated as platform prefixes
77const RESERVED_PATHS = new Set ( [ 'api' , 'wiki' , '_next' , 'favicon.ico' , 'embed' ] ) ;
88
9+ // Check whether Clerk is configured with a valid publishable key
10+ const clerkPubKey = process . env . NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY ?? "" ;
11+ const isClerkEnabled = clerkPubKey . startsWith ( "pk_" ) ;
12+
913// Define public routes that don't require authentication
10- const isPublicRoute = createRouteMatcher ( [
11- "/" , // Landing page
12- "/wiki/projects" , // Cached project browser
13- "/api/(.*)" , // API rewrites to backend
14- "/webhooks/(.*)" , // Webhook endpoints
15- "/_next/(.*)" , // Next.js internals
16- "/favicon.ico" , // Favicon
17- "/.*\\..*" , // Static assets (files with extensions)
18- ] ) ;
19-
20- export default clerkMiddleware ( async ( auth , request ) => {
21- // Public routes pass through without auth checks.
22- // All other routes (e.g. /[owner]/[repo]) go through Clerk's auth
23- // middleware which attaches auth info but does not block access.
24- // Feature gating is handled at the component level.
25- if ( ! isPublicRoute ( request ) ) {
26- // Don't call auth.protect() — we just let Clerk attach auth info.
27- // The wiki viewer components will check auth status themselves.
28- }
14+ const isPublicRoute = isClerkEnabled
15+ ? createRouteMatcher ( [
16+ "/" , // Landing page
17+ "/wiki/projects" , // Cached project browser
18+ "/api/(.*)" , // API rewrites to backend
19+ "/webhooks/(.*)" , // Webhook endpoints
20+ "/_next/(.*)" , // Next.js internals
21+ "/favicon.ico" , // Favicon
22+ "/.*\\..*" , // Static assets (files with extensions)
23+ ] )
24+ : null ;
2925
30- // Platform prefix rewriting: /github/owner/repo → /owner/repo?type=github
26+ /**
27+ * Shared platform-prefix rewrite logic.
28+ * Rewrites /github/owner/repo → /owner/repo?type=github (and likewise for gitlab/bitbucket).
29+ * Returns a NextResponse rewrite if applicable, otherwise null.
30+ */
31+ function handlePlatformRewrite ( request : NextRequest ) : NextResponse | null {
3132 const { pathname, searchParams } = request . nextUrl ;
3233 const segments = pathname . split ( '/' ) . filter ( Boolean ) ;
3334
@@ -46,8 +47,33 @@ export default clerkMiddleware(async (auth, request) => {
4647 return NextResponse . rewrite ( url ) ;
4748 }
4849
49- return NextResponse . next ( ) ;
50- } ) ;
50+ return null ;
51+ }
52+
53+ // When Clerk is enabled, wrap platform rewriting inside clerkMiddleware so
54+ // auth info is attached to every request.
55+ const clerkHandler = isClerkEnabled
56+ ? clerkMiddleware ( async ( auth , request ) => {
57+ // Public routes pass through without auth checks.
58+ // All other routes (e.g. /[owner]/[repo]) go through Clerk's auth
59+ // middleware which attaches auth info but does not block access.
60+ // Feature gating is handled at the component level.
61+ if ( isPublicRoute && ! isPublicRoute ( request ) ) {
62+ // Don't call auth.protect() — we just let Clerk attach auth info.
63+ // The wiki viewer components will check auth status themselves.
64+ }
65+
66+ return handlePlatformRewrite ( request ) ?? NextResponse . next ( ) ;
67+ } )
68+ : null ;
69+
70+ // When Clerk is NOT available (e.g. during Docker build or when key is not
71+ // configured), use a plain middleware that only handles platform rewrites.
72+ function plainMiddleware ( request : NextRequest ) {
73+ return handlePlatformRewrite ( request ) ?? NextResponse . next ( ) ;
74+ }
75+
76+ export default isClerkEnabled ? clerkHandler ! : plainMiddleware ;
5177
5278export const config = {
5379 matcher : [
0 commit comments