Skip to main content

Pattern · TypeScript

Permanent redirects in Next.js (config and middleware)

301/308 for slug changes and duplicate consolidation; watch for loops and canonical drift.

Level: intermediateTime estimate: ~35 min

Permanent redirects consolidate signals on the target URL; temporary ones suit A/B tests and maintenance without rewriting the index.

  • One target URL per intent
  • avoid chains A→B→C
  • after migrations refresh the sitemap and internal links

Redirects close duplicates (/page, /page/), move traffic after section renames, and glue old campaign URLs to canonical targets.

Code

next.config.mjs (fragment):

/** @type {import('next').NextConfig} */
const nextConfig = {
  async redirects() {
    return [
      { source: '/old-path', destination: '/new-path/', permanent: true },
    ]
  },
}
export default nextConfig

Conditional redirect in middleware (e.g. non-production only):

import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'

export function middleware(request: NextRequest) {
  if (request.nextUrl.pathname === '/legacy') {
    return NextResponse.redirect(new URL('/current/', request.url), 308)
  }
  return NextResponse.next()
}

Verification

  • Response status is 301 or 308; Location points at the canonical URL.
  • No loops; at most one or two hops for important URLs.

Sources

Need this implemented for your domain and stack?

Short form: name, phone, and site. After you submit, we reply with next steps and a phase outline; details are refined on a call.