Tutorial5 min readMarch 2026

Understanding Protected Routes in Next.js with Middleware

O

Olamilekan Kilani

Frontend Developer

What are Protected Routes?

Protected routes are pages that should only be accessible to authenticated users. For example, a user's profile page or checkout page should redirect to login if the user isn't logged in.

The Wrong Way — Client-Side Only

Many beginners check authentication inside the component using useEffect:

useEffect(() => {
  const token = localStorage.getItem('token');
  if (!token) router.push('/login');
}, []);

The problem? The page renders briefly before the redirect — users see a flash of the protected content. This is called FOUC (Flash of Unstyled/Unauthorized Content).

The Right Way — Next.js Middleware

Next.js middleware runs on the server before the page loads. No flash, no delay.

// src/middleware.ts
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";

const protectedRoutes = ["/profile", "/checkout"];

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

  if (protectedRoutes.some((route) => pathname.startsWith(route))) {
    const token = request.cookies.get("token")?.value;
    if (!token) {
      return NextResponse.redirect(
        new URL("/login?redirect=" + pathname, request.url)
      );
    }
  }

  return NextResponse.next();
}

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

Why Cookies and Not localStorage?

Middleware runs on the server — it has no access to localStorage. Cookies are sent with every request automatically, so the server can read them.

When the user logs in, save the token to both:

localStorage.setItem('token', data.token);
document.cookie = `token=${data.token}; path=/; max-age=${7 * 24 * 60 * 60}`;

Conclusion

Always use middleware for route protection in Next.js. It's cleaner, faster and more secure than client-side checks.