Redirecting with Style: Crafting Middleware Redirects in Next.js App Router

Redirecting with Style: Crafting Middleware Redirects in Next.js App Router

You may want to think about middleware in Next.js as the bouncer of your application. The middleware takes action before the app serves any page, whether it is the main welcome page or an auxiliary page. The bouncer will let you specify what actions to take on the predefined requests. It can be any action you want- like redirecting the user to a login screen, marking an old page for deprecation, or doing some A/B testing considerations.

In other parts of this tutorial, we will be using TypeScript so we will first create a 'middleware.ts' file. If you are not using TypeScript, you can create a javascript file and name it 'middleware.js'. In any case, every page will need to import some components from Next.js and implement the logic for URL validation function. From that point, it becomes trivial to decide whether to let them through or to redirect them elsewhere.

Moreover, this does not need to be executed on all the routes. The matcher refines the sender scope execution point, meaning you are not constrained to a single route. That is one area we will investigate in these pages.

⚙️ 1. Spinning Up Your Middleware File  

To begin, create a middleware.ts file in the root folder of your project (or under /src if that is how you prefer organizing things). After that, pull the appropriate pieces that need to be fetched.  

// /middleware.ts
import { NextRequest, NextResponse } from 'next/server'

Isn’t that simple? This file will execute for every single request that is received—unless told otherwise. Next.js by Vercel - The React Framework.  

Narrowing the Scope with matcher  

Allowing middleware to run everywhere may slow things down and cause an infinite back and forth. Add a config block:  

With this, you’re only intercepting traffic to those paths. No endless loops, promise. Next.js by Vercel - The React Framework,.

🔄 2. Your First Redirect  

This one had you in the first half, didn’t it?  

Inside your middleware function, look through the URL to decide:  

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

  if (pathname === '/old-page') {
    return NextResponse.redirect(new URL('/new-page', request.url))
  }

  return NextResponse.next()
}

“Here, anyone accessing /old-page is a smooth sail to /new-page. Notice that we use new URL('/new-page', request.url) so that we do not mess the domain or protocol or something unnecessarily” Next.js by Vercel - The React Framework.

Keeping a Sight on Your Private Routes (The Secret Ones😉)

What if you had your own personal dashboard/portal that you only wanted your users to access when logged in? It could function something like this: 

import { authenticate } from './lib/auth'

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

  if (!isAuth && pathname.startsWith('/dashboard')) {
    return NextResponse.redirect(new URL('/login', request.url))
  }

  return NextResponse.next()
}

In case you are not signed in or Authorized and you want to take a look into /dashboard/*, then you will immediately be taken to /login with no questions asked.

🏷️ 3. Combative Dynamism and Multi-Purpose Catch-All Routes

Perhaps your paths include variables such as blog slugs, not a problem at all:

export const config = { matcher: ['/blog/:slug*'] }

export function middleware(request: NextRequest) {
  const slug = request.nextUrl.pathname.split('/')[2]

  if (slug === 'deprecated-post') {
    return NextResponse.redirect(new URL('/', request.url))
  }

  return NextResponse.next()
}

The :slug* The pattern is capable of capturing every single blog URL, and inspecting that portion is almost instant.

📜 4. Redirects: Temporary vs. Permanent

Without any changes, NextResponse.redirect() defaults to issuing 307 Temporary Redirect, which is useful in those scenarios where it’s “Just this once.” For scenarios with “never coming back,” use 308 Permanent: 

return NextResponse.redirect(
  new URL('/new-home', request.url),
  308
)

Increased SEO effectiveness. Help search engines reindex after shifting their focus to relying on updated current data available.

🛠️ 5. It’s the Applying That Counts

Test the app by running the command: npm run dev. Access your outdated URLs and see if it functions as intended.

Always ensure, not the very last, that is eventually, you check the status code returned (307 or 308) along with.

A step further, ensure the location header is positioning.

Check your Edge logs: From Vercel or other places, ensure your middleware is functioning where you expect them to. Otherwise, there can be other problems as well.

🤔 Troubleshooting Tips for easy debugging

Check for infinite loops your matcher may be in best case scenario looking parked at exclude target path.

Missing styles? Focus more at your underlying issues like, are styles load for redirected pages—don’t forget, middleware acts before layouts appear.

Stored 308 Redirects: You'd look stylish in a 308—popular with l337s. Until you are certain, play around with 307s first.

Less strenuous trace debugging...