stackademic

The leading education platform for anyone with an interest in software development.

Next.js Middleware

Run code before requests complete for auth, redirects, and headers

Overview

Middleware runs at the edge before a request reaches your routes. Place middleware.ts at the project root (or src/). Use it for authentication gates, geolocation redirects, A/B tests, and rewriting URLs.

Syntax / Usage

// middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export 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*', '/api/protected/:path*'],
}

Examples

Add security headers:

export function middleware(request: NextRequest) {
  const response = NextResponse.next()
  response.headers.set('X-Frame-Options', 'DENY')
  response.headers.set('X-Content-Type-Options', 'nosniff')
  return response
}

Locale prefix rewrite:

export function middleware(request: NextRequest) {
  const { pathname } = request.nextUrl
  if (pathname.startsWith('/en') || pathname.startsWith('/es')) {
    return NextResponse.next()
  }
  return NextResponse.redirect(new URL(`/en${pathname}`, request.url))
}

Common Mistakes

  • Running heavy database logic in middleware—keep it fast
  • Overly broad matcher patterns hitting static assets unnecessarily
  • Assuming Node.js APIs are available—middleware runs on the Edge runtime
  • Infinite redirect loops when auth and login paths overlap

See Also

routing api-routes app-router metadata