import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server'; import { type NextFetchEvent, type NextRequest, NextResponse, } from 'next/server'; import createMiddleware from 'next-intl/middleware'; import { AllLocales, AppConfig } from './utils/AppConfig'; const intlMiddleware = createMiddleware({ locales: AllLocales, localePrefix: AppConfig.localePrefix, defaultLocale: AppConfig.defaultLocale, }); const isProtectedRoute = createRouteMatcher([ '/dashboard(.*)', '/:locale/dashboard(.*)', '/onboarding(.*)', '/:locale/onboarding(.*)', '/api(.*)', '/:locale/api(.*)', ]); export default function middleware( request: NextRequest, event: NextFetchEvent, ) { if ( request.nextUrl.pathname.includes('/sign-in') || request.nextUrl.pathname.includes('/sign-up') || isProtectedRoute(request) ) { return clerkMiddleware((auth, req) => { const authObj = auth(); if (isProtectedRoute(req)) { const locale = req.nextUrl.pathname.match(/(\/.*)\/dashboard/)?.at(1) ?? ''; const signInUrl = new URL(`${locale}/sign-in`, req.url); authObj.protect({ // `unauthenticatedUrl` is needed to avoid error: "Unable to find `next-intl` locale because the middleware didn't run on this request" unauthenticatedUrl: signInUrl.toString(), }); } if ( authObj.userId && !authObj.orgId && req.nextUrl.pathname.includes('/dashboard') && !req.nextUrl.pathname.endsWith('/organization-selection') ) { const orgSelection = new URL( '/onboarding/organization-selection', req.url, ); return NextResponse.redirect(orgSelection); } return intlMiddleware(req); })(request, event); } return intlMiddleware(request); } export const config = { matcher: ['/((?!.+\\.[\\w]+$|_next|monitoring).*)', '/', '/(api|trpc)(.*)'], // Also exclude tunnelRoute used in Sentry from the matcher };