Middleware use cases for Next.js: auth guards, redirects, geolocation, A/B testing, with matcher config examples and edge runtime limitations.
Middleware use cases for Next.js: auth guards, redirects, geolocation, A/B testing, with matcher config examples and edge runtime limitations.
BeforeMerge offers hundreds of code review rules, guides, and detection patterns to help your team ship better code.
Middleware runs before every matched request, executing at the edge. It can rewrite, redirect, modify headers, or return responses.
// middleware.ts (project root)
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
export function middleware(request: NextRequest) {
return NextResponse.next();
}
export const config = {
matcher: [
"/((?!_next/static|_next/image|favicon.ico).*)",
],
};export async function middleware(request: NextRequest) {
const token = request.cookies.get("session")?.value;
if (!token && request.nextUrl.pathname.startsWith("/dashboard")) {
return NextResponse.redirect(new URL("/login", request.url));
}
return NextResponse.next();
}
export const config = {
matcher: ["/dashboard/:path*", "/settings/:path*"],
};const redirects: Record<string, string> = {
"/old-page": "/new-page",
"/blog/old-post": "/articles/new-post",
};
export function middleware(request: NextRequest) {
const redirect = redirects[request.nextUrl.pathname];
if (redirect) {
return NextResponse.redirect(new URL(redirect, request.url), 301);
}
return NextResponse.next();
}export function middleware(request: NextRequest) {
const country = request.geo?.country || "US";
const response = NextResponse.next();
response.headers.set("x-user-country", country);
if (country === "DE") {
return NextResponse.rewrite(new URL("/de" + request.nextUrl.pathname, request.url));
}
return response;
}export function middleware(request: NextRequest) {
const bucket = request.cookies.get("ab-bucket")?.value;
const response = NextResponse.next();
if (!bucket) {
const newBucket = Math.random() < 0.5 ? "control" : "variant";
response.cookies.set("ab-bucket", newBucket, { maxAge: 60 * 60 * 24 * 30 });
response.headers.set("x-ab-bucket", newBucket);
} else {
response.headers.set("x-ab-bucket", bucket);
}
return response;
}export const config = {
matcher: [
// Match specific paths
"/dashboard/:path*",
// Match all except static files
"/((?!api|_next/static|_next/image|favicon.ico).*)",
// Match with named params
"/users/:id/settings",
],
};Middleware runs in the Edge Runtime, which means:
fs, path, crypto (use Web Crypto), no Buffer (use Uint8Array)eval(), new Function()