Middleware
Run code before a request completes to redirect, rewrite, or add headers β from a single middleware.ts file.
Syntax
export const config = { matcher: ['/dashboard/:path*'] };Middleware runs on every matching request before it reaches your routes. Use it for auth checks, redirects, rewrites, or setting headers. Define it in a single middleware.ts file at the project root, and export a config.matcher to control which paths it runs on.
Common uses
- Redirect unauthenticated users to a login page.
- Rewrite URLs for A/B tests or localization.
- Attach or read cookies and headers.
Example
// middleware.ts (project root)
import { NextResponse, type NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
const loggedIn = request.cookies.has('session');
if (!loggedIn) {
return NextResponse.redirect(new URL('/login', request.url));
}
return NextResponse.next();
}
export const config = {
matcher: ['/dashboard/:path*'],
};When to use it
- A middleware checks the auth cookie on every /dashboard/* request and redirects unauthenticated users to /login.
- An internationalisation middleware reads the Accept-Language header and rewrites the URL to the correct locale prefix.
- A maintenance-mode middleware redirects all traffic to a /maintenance page by setting a flag in an environment variable.
More examples
Auth redirect middleware
The middleware runs before the route renders and redirects unauthenticated requests away from protected paths.
// middleware.ts (project root)
import { NextRequest, NextResponse } from 'next/server';
export function middleware(req: NextRequest) {
const token = req.cookies.get('auth-token');
if (!token && req.nextUrl.pathname.startsWith('/dashboard')) {
return NextResponse.redirect(new URL('/login', req.url));
}
return NextResponse.next();
}
export const config = { matcher: ['/dashboard/:path*'] };Add security headers
Returning NextResponse.next() with modified headers applies security headers to every response sitewide.
// middleware.ts
import { NextResponse } from 'next/server';
export function middleware() {
const res = NextResponse.next();
res.headers.set('X-Frame-Options', 'DENY');
res.headers.set('X-Content-Type-Options', 'nosniff');
return res;
}Locale rewrite via middleware
NextResponse.rewrite changes the path the server resolves without redirecting the browser, enabling transparent i18n.
// middleware.ts
import { NextRequest, NextResponse } from 'next/server';
const locales = ['en', 'fr', 'de'];
export function middleware(req: NextRequest) {
const lang = req.headers.get('accept-language')?.split(',')[0].slice(0, 2) ?? 'en';
const locale = locales.includes(lang) ? lang : 'en';
return NextResponse.rewrite(new URL(`/${locale}${req.nextUrl.pathname}`, req.url));
}
Discussion