/** * Next.js Middleware * * Handles authentication and route protection */ import { createServerClient } from '@supabase/ssr' import { NextResponse, type NextRequest } from 'next/server' export async function middleware(request: NextRequest) { let supabaseResponse = NextResponse.next({ request, }) const supabase = createServerClient( process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, { cookies: { getAll() { return request.cookies.getAll() }, setAll(cookiesToSet) { cookiesToSet.forEach(({ name, value }) => request.cookies.set(name, value) ) supabaseResponse = NextResponse.next({ request, }) cookiesToSet.forEach(({ name, value, options }) => supabaseResponse.cookies.set(name, value, options) ) }, }, } ) // Refresh session if expired - required for Server Components const { data: { user }, } = await supabase.auth.getUser() const { pathname } = request.nextUrl // Public routes that don't require authentication const publicRoutes = [ '/', '/login', '/reset-password', '/update-password', '/auth/callback', '/contact', '/blog', '/documentatie', '/api/leads', '/robots.txt', '/sitemap.xml', ] // API routes - let them handle auth themselves const isApiRoute = pathname.startsWith('/api/') // Check if current path is public const isPublicRoute = publicRoutes.some(route => pathname === route || pathname.startsWith(`${route}/`) ) // Static files and Next.js internals if ( pathname.startsWith('/_next') || pathname.startsWith('/static') || pathname.includes('.') ) { return supabaseResponse } // Allow API routes to pass through - they handle auth internally if (isApiRoute) { return supabaseResponse } // Redirect to login if not authenticated and trying to access protected route if (!user && !isPublicRoute) { const redirectUrl = new URL('/login', request.url) redirectUrl.searchParams.set('redirect', pathname) return NextResponse.redirect(redirectUrl) } // Helper: get preferred interface redirect path const getPreferredPath = () => { const preference = user?.user_metadata?.preferred_interface return preference === 'cortex' ? '/epd/cortex' : '/epd/clients' } // Redirect to preferred interface if authenticated and trying to access login if (user && pathname === '/login') { return NextResponse.redirect(new URL(getPreferredPath(), request.url)) } // Redirect /epd to preferred interface based on user preference if (user && pathname === '/epd') { return NextResponse.redirect(new URL(getPreferredPath(), request.url)) } return supabaseResponse } export const config = { matcher: [ /* * Match all request paths except: * - _next/static (static files) * - _next/image (image optimization files) * - favicon.ico (favicon file) * - public folder */ '/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)', ], }