How To Permanently Redirect (301, 308) with Next JS

Last Updated:

This post contain affiliate links to Udemy courses, meaning when you click the links and make a purchase, I receive a small commission. I only recommend courses that I believe support the content, and it helps maintain the site.

I recently worked on migrating a large content heavy site from pure WordPress to a headless WordPress and Next JS set up. During this change it was decided that a base URL for a blog section needed changing.

The URL structure was to change from:




For 500+ pieces of content.

To make sure that all the old link juice was not lost, each one of these old links needed to be 301 redirected to the new URL structure.

On previous sites I have used .htaccess (oh, PHP) or handled redirects on the host level (Cloudflare pages make this super easy). But this time I wanted to keep everything internal, as Next JS has the tools to handle it.

What is a 301 Redirect? Why is it Important?

A 301 redirect is a code sent by the web server to the browser, telling it that the URL in question has been permanently moved to another URL. Google will also use this to re-write all of their indexing to the new pages, and pass the ranking power (or link juice) across to the new page.

A 301 redirect should be used when a page (or pages) has been moved or removed from a website.

An easy way to think about a 301 redirect is to think about when you move house. If you do not tell the postal service what your new address is and set up a re-direct, you will not get post that is set to your old address. Telling the postal service about your new address is the same as a 301.

Hang on, Next JS Uses a 308 not 301

This initially concerned me a little. Why would Next JS use a different status code?

Well this is due to how browsers moved the goal posts. As the Next JS docs say:

Traditionally a 302 was used for a temporary redirect, and a 301 for a permanent redirect, but many browsers changed the request method of the redirect to GET, regardless of the original method. For example, if the browser made a request to POST /v1/users which returned status code 302 with location /v2/users, the subsequent request might be GET /v2/users instead of the expected POST /v2/users. Next.js uses the 307 temporary redirect, and 308 permanent redirect status codes to explicitly preserve the request method used.

In essence, a 308 is more reliable.

So does Google treat a 308 the same as a 301? Is this going to cause issues for search indexing? No, this will not cause any issues. Google’s Search Advocate John Mueller, has said that 308 redirects are treated in the same way as 301 by Google crawlers. Here is his tweet about it.

How to Set up a Permanent Redirect in Next JS

Next JS is essential a React App bundled up with a number of other third party packages, and other really helpful internal functions. Some of these packages and functions help with the speediness of the site. Others handle how a user is able to navigate around the site with different URLs.

A lot of Next.js magic comes from the next.config.js file. Here you can set up any number of options, but the one we care about it the redirects function.

module.exports = {
    // All the other config options you may have...
    async redirects() {
        return [
                // What the user typed in the browser
                source: '/articles/:path*',
                // Where the user will be redirected to
                destination: '/blog/:path*',
                // If the destination is a permanent redirect (308)
                permanent: true

The above object shows setting the `source` value to “article” with a catch all of any URL after the initial string. It then sets the destination using the same logic.

Using the :path* is known within Next JS as Wildcard Path Matching. For example /blog/:slug* will match /blog/a/b/c/d/content-piece.

Finally permanent is set to true. This tells Next JS that the redirection should be sent with a status code of 308. If this is set to false then it sends a 307 (traditionally this would have been 302, but Next JS changed this due to the reasoning outlined above).

Hopefully this helped you, and if you have any questions you can reach me at: @robertmars

Related Posts

Helpful Bits Straight Into Your Inbox

Subscribe to the newsletter for insights and helpful pieces on React, Gatsby, Next JS, Headless WordPress, and Jest testing.