How to manage redirects in Gatsby automatically

By Ido Schacham, Senior software developerApr 20, 2022Read time 5 min
Untitled design (15)

Gatsby is a Frontend framework that generates static pages. When the paths of your pages are changed, Gatsby will generate a page for the new path by default and remove the old one. How can you, as a developer, manage redirects in Gatsby automatically to avoid this problem?

Our company’s website, https://wunderdog.io, is based on Gatsby + Contentful. Recently, we have been creating a “news” page, which we later renamed from /latest-news to /news in our CMS. After the name change, Gatsby generated a new path removing the old one. I was sure I would find a Gatsby plugin solving this problem to automatically track page path changes to create redirects. WordPress, for example, has plenty of plugins that do this. To my surprise, I found none. Neither did my colleagues.

This seemingly innocent problem affects links previously shared on social media or other websites, which cease to work. By clicking it, you get a 404, thus resulting in lost traffic. Concurrently, the page’s SEO score may be damaged since Google will not know all the links pointing to https://wunderdog.io/latest-news are actually intended to point to https://wunderdog.io/news. The solution, of course, is to create redirects (e.g., from /latest-news to /news). This way you can get users to load the right page and keep the page’s SEO score intact.

Step 1: Creating the Gatsby plugin for automatic redirections

The first step I set out to do, was to create a shiny new local Gatsby plugin with the sexy name of gatsby-plugin-automatic-redirects, a plugin that updates redirects automatically, at build time and efficiently, with as little configuration as possible. Luckily, Gatsby offers the onCreatePage API, which is called whenever a new page is created. Thus, the latest page paths can easily be retrieved. But how can we know which paths have changed and for which pages?

The simple solution is to maintain a JSON object with page IDs as keys and page paths as values. This way, it’s possible to check the previous path for a page, and determine whether it changed or not. Nonetheless, since there is no automatic ID assigned to pages–as far as I know–it would need to be passed somehow to onCreatePage. This is slightly annoying, but the plugin requires the page ID to be passed via the page context in gatsby-node.js.

exports.createPages = async ({
  graphql,
  actions
}) => {
  const result = await graphql(`
    query {
      allContentfulPage {
        edges {
          node {
            contentful_id
            slug
          }
        }
      }
    }
  `)

  const {
    createPage
  } = actions

  result.data.allContentfulPage.edges.forEach(({
    node
  }) => {
    const {
      slug,
      contentful_id
    } = node

    createPage({
      path: `/${slug}`,
      component: path.resolve("./src/templates/page.js"),
      context: {
        id: contentful_id,
      },
    })
  })
}

Step 2: How to save the redirects

Reading and saving redirects requires keeping a separate JSON object to make sure the redirects are up to date. Now, what about:

  • Circular redirects. For example, if the path /latest-news was changed to /news and then back to /latest-news, then the redirects /latest-news -> /news and /news -> /latest-news would be added. That would create an infinite redirect loop. The solution is to keep the latest redirect of /news -> /latest-news and remove any redirects that are from /latest-news to anything else.

  • Transitional redirects, What if /latest-news is changed to /recent-news and then to /news? By default, that would create redirects for /latest-news -> /recent-news and /recent-news -> /news. It’s not bad per se, but it’s a bit redundant to have to jump through two hoops from /latest-news. Instead, the redirect of /latest-news -> /recent-news should be changed to /latest-news -> /news

  • Pages that have been totally removed. Anything that redirects to them should be deleted. The plugin does this as well. Check! 

The plugin also calls Gatsby’s createRedirect action to tell Gatsby that these redirects should be created. However, the plugin does not implement the redirect creation itself, as this depends on the hosting solution. There are plenty of other plugins for that, such as gatsby-plugin-meta-redirect, gatsby-plugin-s3, gatsby-plugin-nginx-redirect, and others. Without such a plugin, the redirects won’t work.

Step 3: Storing the pages and redirects JSON objects

The easiest solution to store pages and redirects JSON objects is the file system. We can read the JSON objects from files and then store them right back again. Should one wish to have any custom redirects, we can also manually edit the redirects file. The files need to be a part of the repository, though, so that the latest data is always available.

For wunderdog.fi, this was implemented via the GitHub git-auto-commit-action running right after the site build. If someone wants to read and store the page and redirect JSONs somewhere else (e.g., a CMS or a database), the plugin allows it via the getData and saveData options.

Step 4: An up-and-running Gatsby plugin for everyone

gatsby-plugin-automatic-redirects was first developed as a local Gatsby plugin for wunderdog.fi. After being up and running for several weeks, the plugin seemed stable. It even worked and created a redirect for a blog post. There didn’t seem to be any implications to the build time either. I decided to release it to the public as open-source, and I hope that it will help you and your users reach your website and keep your SEO scores with as many path changes as possible.

Learn more about Wunderdog's OSS program, which sponsors open-source contributions by our people to support independent learning and development.