UNPKG

starkon

Version:

Complete Next.js boilerplate with authentication, i18n & CLI - Create production-ready apps instantly

113 lines (94 loc) 3.58 kB
/* eslint-disable @typescript-eslint/no-explicit-any */ import { NextResponse } from 'next/server' import type { NextRequest } from 'next/server' // Public routes that don't require authentication const publicRoutes = [ '/login', '/register', '/forgot-password', '/reset-password', '/login', '/register', '/forgot-password', '/reset-password', ] // Routes that should redirect to dashboard if user is already authenticated const authRoutes = ['/login', '/register', '/forgot-password', '/reset-password'] // Supported locales for language management const supportedLocales = ['tr', 'en'] as const const defaultLocale = 'tr' /** * Handle language management logic */ function handleLanguageLogic(request: NextRequest): NextResponse | null { const url = request.nextUrl.clone() const langParam = url.searchParams.get('lang') const cookieLocale = request.cookies.get('language')?.value // If URL has valid lang parameter, update cookie and continue if (langParam && supportedLocales.includes(langParam as any)) { const response = NextResponse.next() response.cookies.set('language', langParam, { maxAge: 365 * 24 * 60 * 60, // 1 year path: '/', sameSite: 'lax', secure: process.env.NODE_ENV === 'production', }) return response } // If no lang param but cookie exists with non-default locale, redirect with lang param if (!langParam && cookieLocale && supportedLocales.includes(cookieLocale as any) && cookieLocale !== defaultLocale) { url.searchParams.set('lang', cookieLocale) return NextResponse.redirect(url) } return null // No language-related redirect needed } export function middleware(request: NextRequest) { const { pathname } = request.nextUrl // Skip middleware for static files and API routes (except auth) if ( pathname.startsWith('/_next') || (pathname.startsWith('/api') && !pathname.startsWith('/api/auth')) || pathname.startsWith('/static') || pathname.includes('.') // Skip files with extensions ) { return NextResponse.next() } // Handle language logic first (for all routes except skipped ones) const languageResponse = handleLanguageLogic(request) if (languageResponse) { return languageResponse } // Root route - allow access (will show public home page) if (pathname === '/') { return NextResponse.next() } // Check if route is public const isPublicRoute = publicRoutes.some((route) => pathname === route || pathname.startsWith(route + '/')) const isAuthRoute = authRoutes.some((route) => pathname === route) // Since we're using sessionStorage (client-side only), we can't check tokens in middleware // Middleware runs on server-side, so we'll handle auth logic in client components // For auth routes, let them through - AuthProvider will handle redirects if (isAuthRoute) { return NextResponse.next() } // For public routes, allow access if (isPublicRoute) { return NextResponse.next() } // For protected routes, let them through - ProtectedRoute component will handle auth check // This is because sessionStorage is not available in server-side middleware return NextResponse.next() } export const config = { matcher: [ /* * Match all request paths except for the ones starting with: * - api (API routes) * - _next/static (static files) * - _next/image (image optimization files) * - favicon.ico (favicon file) * - public files (public folder) */ '/((?!api|_next/static|_next/image|favicon.ico|public).*)', ], }