Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
API Endpoints  ›  Capstone Project

Redirects

Reditects 13 minA redirect answers a request by pointing the visitor at another URL, with 307 for temporary moves and 308 for permanent ones, set in config, in code, or in a route handler.

Redirects

Trailhead once put its trail pages under /hikes/…, and hundreds of old links still point there. Meanwhile, the saved-trails page must send signed-out visitors to the login screen. Both are redirects: answering a request with "not here, go there". They differ in whether the move is forever and in when you know it is needed.

The rule

Known ahead and forever: config, 308. Decided per request: redirect(), 307.

A redirect is a response with a 3xx status and a Location header. The two you use in Next.js:

Status Meaning Browsers and search engines
307 Temporary Redirect "Go there for now" Keep the old URL
308 Permanent Redirect "It lives there now" Update to the new URL

Both keep the request method, so a POST stays a POST.

1. In next.config.ts, for moves you know before any request arrives:

// next.config.ts
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  async redirects() {
    return [
      { source: "/hikes/:slug", destination: "/trails/:slug", permanent: true },
    ];
  },
};
export default nextConfig;

:slug carries the matching part across. permanent: true gives 308; false gives 307. These run before any page code.

2. In code, with redirect() from next/navigation, when the decision depends on the request. It works in server components, route handlers and server actions:

// app/saved/page.tsx
import { redirect } from "next/navigation";
import { getSession } from "@/lib/auth";

export default async function SavedPage() {
  const session = await getSession();
  if (!session) redirect("/login");     // 307; nothing below runs
  return <SavedTrails hikerId={session.hikerId} />;
}

redirect() works by throwing a special signal that Next.js catches, so code after it never runs. Do not wrap it in try/catch, or you may swallow the signal. For a permanent move decided in code, permanentRedirect() sends 308.

In a route handler you can also return NextResponse.redirect(new URL("/login", request.url)), which needs an absolute URL; building it from request.url handles that.

The shortcut

Ask two questions: "Do I know it before the request?" and "Is it forever?" Known ahead: config. Needs the request: redirect(). Forever: 308. For now: 307.

Trailhead's two redirectsStep 1 of 4
  1. /hikes/:slug → /trails/:slug

    Known ahead and forever. A config entry with permanent: true: 308.

The trap is using a permanent redirect for something temporary. Browsers may cache a 308 and keep skipping the old URL even after you change your mind.

Drills

Answer fast — trust the rule.

quick drill

A config redirect has permanent: true. Which status is sent?

quick drill

Which fits "send signed-out visitors from /saved to /login"?

quick drill

What happens to code written after redirect("/login") in a component?

quick drill

In { source: "/hikes/:slug", destination: "/trails/:slug" }, where does /hikes/fox-hollow go?

Remember

  • Known ahead and forever: a config redirect with permanent: true (308). Decided per request: redirect() (307).
  • Shortcut: "known before the request?" and "is it forever?"
  • Trap: redirect() throws, so do not catch it, and never make a temporary move permanent.

Practice — level up

0/1 solved

Write your answer, then compare it with a rubric and a model answer.

ExplainSend them the right way

Trailhead renamed /hikes/:slug to /trails/:slug for good, and the saved-trails page must send signed-out visitors to /login. Explain which redirect tool you use for each and which status code results.