Protected Routes: Server Gates, Not Hidden Links
A protected route is a server-enforced gate, not a hidden link. In Next.js, middleware or server components validate sessions before HTML ships, which matters for dashboards and billing.
WHY IT EXISTS: In single-page applications, every route is just a JavaScript chunk waiting to be executed. If authorization only hides a navigation link, a user can still type /admin directly into the address bar and the bundler will serve the file. Protected routes exist because the client is untrusted; the server must decide who receives the HTML and data.
THE MENTAL MODEL: Think of a protected route as a nightclub with a bouncer at the door rather than a curtain inside the room. The bouncer checks ID before entry. In web terms, the check must happen at the network boundary before bytes cross the wire. A client-side redirect is like hanging a please do not enter sign on an unlocked door.
HOW IT WORKS: In the Next.js App Router, protection typically lives in middleware or inside a server component. Middleware runs at the edge, inspects the session cookie, and issues a redirect before the request reaches application code. If the guard is inside a server component, it reads the cookie using the built-in cookies helper, validates it against an auth service, and calls redirect if the session is missing or invalid. In React Router, the equivalent is a loader that runs before the component mounts; it fetches the user profile and throws a redirect if the user is anonymous. The protected payload must never ship until the gate opens.
WHEN TO USE IT: Use server-level route protection for any page that renders personal data, financial information, administrative controls, or paywalled content. Use client-side guards only as UX polish, such as showing a login modal instead of a blank screen, but always pair them with a server check that runs first.
WHEN NOT TO USE IT: Do not rely on conditional rendering in a client component to hide sensitive content. Do not validate tokens by parsing localStorage in the browser and trusting the result. Do not run heavy database lookups in edge middleware on every request if you can scope the check to specific route segments, because that adds cold-start latency to every matching request.
ONE CANONICAL EXAMPLE: A SaaS application has a dashboard revenue page built in Next.js App Router. The layout file in the dashboard segment imports the cookies helper from Next.js headers, looks for a session token, and verifies it with the auth provider. If verification fails, it calls redirect to /login. Additionally, middleware uses a matcher for /dashboard/:path* to catch direct requests at the edge. When an unauthenticated user visits the URL, they receive a 307 redirect to /login and the revenue data never leaves the database.
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.