← All lessons
Lesson 15 · Advanced

Middleware

Run code before a request reaches a page. Auth, redirects, rewrites and A/B tests live here.

Middleware is a single function that runs on every matching request, before any page or route handler. It runs on the Edge runtime by default — fast, but with a restricted Node API.

The file

Create middleware.js at the root of the project (next to app/, not inside it).

// middleware.js
import { NextResponse } from "next/server";

export function middleware(request) {
  const { pathname } = request.nextUrl;

  if (pathname.startsWith("/admin")) {
    const isLoggedIn = Boolean(request.cookies.get("session"));
    if (!isLoggedIn) {
      return NextResponse.redirect(new URL("/login", request.url));
    }
  }

  return NextResponse.next();
}

export const config = {
  matcher: ["/admin/:path*", "/account/:path*"],
};

What middleware can return

  • **NextResponse.next()** — continue to the page.
  • **NextResponse.redirect(url)** — send the user elsewhere.
  • **NextResponse.rewrite(url)** — keep the URL but render a different route.
  • **new Response(body, init)** — short-circuit with your own response (e.g., 401).

Matchers

The matcher config narrows down which paths trigger middleware. Use it religiously — running middleware on every static asset is wasteful.

export const config = {
  matcher: [
    "/dashboard/:path*",
    "/api/:path*",
    {
      source: "/((?!_next/static|_next/image|favicon.ico).*)",
      missing: [{ type: "header", key: "x-skip-mw" }],
    },
  ],
};

Setting headers and cookies on responses

const res = NextResponse.next();
res.cookies.set("session-touched", Date.now().toString());
res.headers.set("x-country", request.geo?.country ?? "unknown");
return res;
Note: Middleware is fast but limited. Don't run heavy DB queries or large dependencies there. Most apps use middleware only for auth gates, locale redirects and feature flags.

Try it

Write middleware that redirects any unauthenticated request to `/account/*` to `/login`. Users are authenticated when there is a `token` cookie.

Need a hint?

Read the cookie with request.cookies.get() and redirect when it's missing.

Quiz

Pick the best answer. You only get one shot per question.

1. Where must the middleware file live?

2. Which return value lets the request continue to its original destination?

3. Why use a `matcher` config?