How to properly handle URL slug changes in Next.js

Rate this content
Bookmark

If you're using a headless CMS for storing content, you also work with URL slugs, the last parts of any URL. The problem is, content editors are able to freely change the slugs which can cause 404 errors, lost page ranks, broken links, and in the end confused visitors on your site. In this talk, I will present a solution for keeping a history of URL slugs in the CMS and explain how to implement a proper redirect mechanism (using TypeScript!) for dynamically generated pages on a Next.js website.

Add to the talk notes: https://github.com/ondrabus/kontent-boilerplate-next-js-ts-congress-2022 

10 min
29 Apr, 2022

Comments

Sign in or register to post your comment.

AI Generated Video Summary

This Talk explains how to handle URL slug changes in Next.js by using the getStaticPaths and getStaticProps methods. It covers implementing redirects and provides a solution to eliminate the need for editors to perform additional steps. The approach involves tracking URL slug changes and issuing proper redirects. The speaker encourages the audience to reach out with any questions or experiences with handling URL slugs.

1. Handling URL Slack Changes in Next.js

Short description:

Hello, everyone. I'm Andrey, developer evangelist at Content by Kentico. Today, I'll explain how to handle URL Slack changes in Next.js. Every content item in the headless CMS contains a URL slag, and when the editor changes it, the old URL slag ceases to exist, resulting in 404 errors for visitors. To properly handle this, we need to know the URL slag history and use the getstaticpaths and getstaticprops methods in Next.js to issue redirects. Let's start with the content side, where we can use the urlslug-history custom element to track URL slag changes.

Hello, everyone. I'm Andrey, developer evangelist at Content by Kentico. And today, I want to tell you how to properly handle URL Slack changes in Next.js.

Now, first of all, why should we care about the URL slags? Every content item that is stored in the headless CMS and you are actually storing it or displaying it as a page in your site implementation contains a URL slag. Now, the problem is when editor comes into that content item, changes the URL slag, and your site implementation just takes the change, rebuilds the page, and the old page, the old URL slag just ceases to exist. The problem is if that page used to have a good page rank on search engines, or you used that page in your marketing campaigns, all those visitors that are using that URL will now get 404 errors. And these days we cannot really afford confused visitors, right?

So, what we need to do is, first, we need to know for every page, every content item, we need to know the URL slag history. You see here, the example is that the current page has a URL slug, hello-typescript-congress, but in the past it used to have a URL slug, typescript-congress and hello-conference, we need to know the history in order to be able to issue the redirects properly. Next thing is for the Next.js, now we're going to be using Next.js and content in this example, but if you're using a different framework, you can apply the same principles there. Here we're just talking about Next.js, so we have two methods. We have getstaticpaths and getstaticprops. In getstaticpaths, we need to provide all the URL slugs where there is a page for us to generate. In that case, we need to provide all the three URL slugs. So, that's the history ones and the current ones as well. And the last step, the third step is to add a proper redirect in getstaticprops. There we need to find out based on the slug, whether this is a current slug, like the hello-typescript-congress, which is the target page, or whether the slug that we're using is a historic one, and we should redirect the visitor to a current page. In this case, that would be the typescript-congress, hello-conferences, which will issue redirects. So how can we do this in Next.js? Let's take a look. Let's start in content first. On the content side of things, I prepared one content type called conference. And when you look at the content item, that's already using that content type. You see in content we have a special urlslug-history custom element that you can use on your project. It's available open source, so we can just deploy it to Netlify or Vercel and use it just like I'm using it here. It actually tracks all the changes you do to a urlslug. So you see here, now the urlslug is typescript-congress-2022. If I change it to typescript-congress, it automatically registers the change. And when I publish the page, it's going to store the change within the content item. So you see this is in the history. Now, we can do this as many times as we want. We're just going to get a list of strings out of the API, but this is the first step.

2. Implementation of URL Slug Changes in Next.js

Short description:

In Next.js, you need to provide all the paths to getStaticPaths or as a result to Next.js. In getStaticProps, you need to issue the redirect if it's a page that should be redirected. We create a list of all the slugs and all the current slugs that they should redirect to. We store all the paths in the cache and provide all the slugs, historic ones and current ones, back to Next.js. We issue a proper redirect if we find out we should.

You need to know all the urlslugs, the historic ones and the current ones. Now let's take a look at the implementation. In Next.js, I have a simple page, slug-tsx. Now this whole thing is based on a Next.js content boilerplate, so there is not a ton of functionality. But here you see there are two methods, getStaticPaths, getStaticProps. And as I mentioned in the presentation at the start, you need to provide all the paths to getStaticPaths or as a result, to Next.js.

In getStaticProps, you need to issue the redirect if it's a page that should be redirected. So here we just need to do one simple change and add to the elements parameter the history as well. So before, we were only using the URL slug, but now we want to use the URL slug history as well to get really all the paths. And now we need to get all the paths in a simple list.

Now the thing is, if we only get the paths in getStaticProps, we would have to do one additional API check with the content API to see if the slug is a historic one or a current one. So what I'm going to do is I'm going to create a list of all the slugs and all the current slugs that they should redirect to. Now, I'm going to do the implementation here, I'm going to fast forward and then I'm going to explain the code in a second.

Right, so what I implemented here is we're getting all paths from the content CMS, and we're actually providing all those paths back as an IPagePath structure, which you can see contains just two properties path and redirectsTo. Path is the URL slug, the current one, and redirectsTo is, in case we're working with the historic path, here we're going to hold the current path of any page. So you see that for the actual item coming from content, we're providing a path that is the current path of the item, the one of the published version of the page. And then we're creating a structure of the historic paths, historic slugs, and they redirect all to the current page path.

Now the problem is, we cannot really take the whole structure and provide it to Next.js so that we get it in getStaticProps. The reason is, Next.js will only allow us to transfer the slug, because it's in the filename, it's the variable on the way to the page. So we're not going to be able to transfer this to getStaticProps and avoid the performance problems. So what we're going to do is, we're going to do a workaround suggested by Versal, where we're just going to take all the paths, we're going to serialize them into a physical file, and then we're going to take that file back in getStaticProps. I'm just going to again do the implementation and fast forward.

Now you see here that I'm storing all the paths in the cache. The last thing I need to do here is to provide all the slugs, right, this is the second point from the presentation. We need to get all the paths, historic ones and current ones, and return it back to Next.js here. Because we're just telling Next.js, on this path, there is not a 404, there is a page here. And now we need to do the third step, and that is issue a proper redirect if we find out we should. So, in this case, we're just taking the path from cache and if there is a page that should be redirected, it will have the redirects.to field. Because these are all the historic URLs slugs, and we need to redirect them to this path. So, we can do a simple condition here, if path.redirects.to exists.

3. Implementing Redirects and Final Thoughts

Short description:

In order to perform the redirect, we need to return a redirect object that includes the destination and permanent fields. The destination should be set from the root of the site, and the permanent field determines whether a 307 or 308 redirect is used. After implementing the solution, we can test it by refreshing the page. The current URL slack should display the corresponding page, and appending the previous slack should redirect to the correct page. While the implementation may not be ideal, it eliminates the need for editors to perform any additional steps. If you have any questions or want to share your experience with handling URL slacks, feel free to reach out to me on Twitter.

In that case, we want to do the redirect. So, we're going to return a redirect object, and the redirect object only needs to contain a destination and a permanent. So, permanent, if you want to do 307 or 308 redirect, based on that, set the permanent field. I want permanent to be true. And in the destination, just remember if you're in the subfolder or if you're in the root, this is going to be destination from the root of your site. So in my case it's just a slash and path it redirects to. So let's save this.

There is still a problem here under get static paths. Right. I forgot. Yes there is path dot path, because here we're getting just the object, so we want the slack in there. Now, this is fine. So let's try to run the site. And let's go back to the browser and refresh this page. Now, the current URL slack is TypeScript Congress. So on that page on the URL slack we should have TypeScript Congress page. So you see this is working. And the previous slack was TypeScript Congress 2022. So if we append here 2022 we should get redirected to TypeScript Congress. So it works as expected.

Now, the implementation isn't ideal to be honest, but it works this way and lets us put everything in order. And it does not, that's the most important thing, it does not require editors to do any extra steps. It just works. And that's all from me. If you want to get more information about this solution or you want to share your experience handling URL slacks, then definitely reach out to me. You can find me on Twitter.

Check out more articles and videos

We constantly think of articles and videos that might spark Git people interest / skill us up or help building a stellar career

React Summit 2022React Summit 2022
20 min
Routing in React 18 and Beyond
Concurrent React and Server Components are changing the way we think about routing, rendering, and fetching in web applications. Next.js recently shared part of its vision to help developers adopt these new React features and take advantage of the benefits they unlock.
In this talk, we’ll explore the past, present and future of routing in front-end applications and discuss how new features in React and Next.js can help us architect more performant and feature-rich applications.
Vue.js London 2023Vue.js London 2023
30 min
Stop Writing Your Routes
The more you keep working on an application, the more complicated its routing becomes, and the easier it is to make a mistake. ""Was the route named users or was it user?"", ""Did it have an id param or was it userId?"". If only TypeScript could tell you what are the possible names and params. If only you didn't have to write a single route anymore and let a plugin do it for you. In this talk we will go through what it took to bring automatically typed routes for Vue Router.
React Summit 2023React Summit 2023
27 min
The New Next.js App Router
Next.js 13.4 recently released the stable version of the "App Router" – a transformative shift for the core of the framework. In this talk, I'll share why we made this change, the key concepts to know, and why I'm excited about the future of React.
TypeScript Congress 2023TypeScript Congress 2023
31 min
Making Magic: Building a TypeScript-First Framework
I'll dive into the internals of Nuxt to describe how we've built a TypeScript-first framework that is deeply integrated with the user's IDE and type checking setup to offer end-to-end full-stack type safety, hints for layouts, middleware and more, typed runtime configuration options and even typed routing. Plus, I'll highlight what I'm most excited about doing in the days to come and how TypeScript makes that possible not just for us but for any library author.
React Advanced Conference 2023React Advanced Conference 2023
28 min
A Practical Guide for Migrating to Server Components
Server Components are the hot new thing, but so far much of the discourse around them has been abstract. Let's change that. This talk will focus on the practical side of things, providing a roadmap to navigate the migration journey. Starting from an app using the older Next.js pages router and React Query, we’ll break this journey down into a set of actionable, incremental steps, stopping only when we have something shippable that’s clearly superior to what we began with. We’ll also discuss next steps and strategies for gradually embracing more aspects of this transformative paradigm.

Workshops on related topic

React Advanced Conference 2021React Advanced Conference 2021
174 min
React, TypeScript, and TDD
Featured WorkshopFree
ReactJS is wildly popular and thus wildly supported. TypeScript is increasingly popular, and thus increasingly supported.
The two together? Not as much. Given that they both change quickly, it's hard to find accurate learning materials.
React+TypeScript, with JetBrains IDEs? That three-part combination is the topic of this series. We'll show a little about a lot. Meaning, the key steps to getting productive, in the IDE, for React projects using TypeScript. Along the way we'll show test-driven development and emphasize tips-and-tricks in the IDE.


React Advanced Conference 2022React Advanced Conference 2022
148 min
Best Practices and Advanced TypeScript Tips for React Developers
Featured Workshop
Are you a React developer trying to get the most benefits from TypeScript? Then this is the workshop for you.
In this interactive workshop, we will start at the basics and examine the pros and cons of different ways you can declare React components using TypeScript. After that we will move to more advanced concepts where we will go beyond the strict setting of TypeScript. You will learn when to use types like any, unknown and never. We will explore the use of type predicates, guards and exhaustive checking. You will learn about the built-in mapped types as well as how to create your own new type map utilities. And we will start programming in the TypeScript type system using conditional types and type inferring.
React Summit 2022React Summit 2022
173 min
Build a Headless WordPress App with Next.js and WPGraphQL
WorkshopFree
In this workshop, you’ll learn how to build a Next.js app that uses Apollo Client to fetch data from a headless WordPress backend and use it to render the pages of your app. You’ll learn when you should consider a headless WordPress architecture, how to turn a WordPress backend into a GraphQL server, how to compose queries using the GraphiQL IDE, how to colocate GraphQL fragments with your components, and more.
React Day Berlin 2022React Day Berlin 2022
53 min
Next.js 13: Data Fetching Strategies
WorkshopFree
- Introduction
- Prerequisites for the workshop
- Fetching strategies: fundamentals
- Fetching strategies – hands-on: fetch API, cache (static VS dynamic), revalidate, suspense (parallel data fetching)
- Test your build and serve it on Vercel
- Future: Server components VS Client components
- Workshop easter egg (unrelated to the topic, calling out accessibility)
- Wrapping up
React Advanced Conference 2023React Advanced Conference 2023
102 min
Fetch, useEffect, React Query, SWR, what else?
WorkshopFree
In this workshop, first, we’ll go over the different ways you can consume APIs in React. Then, we’ll test each one by fetching content from a headless CMS (with both REST and GraphQL) and checking in detail how they work.
While there is no advanced React knowledge required, this is going to be a hands-on session, so you’ll need to clone a preconfigured GitHub repository and utilize your preferred React programming editor, like VS Code.
You will learn:
- What diverse data fetching options there are in React
- What are advantages and disadvantages of each
- What are the typical use cases and when each strategy is more beneficial than others
TypeScript Congress 2022TypeScript Congress 2022
116 min
Advanced TypeScript types for fun and reliability
Workshop
If you're looking to get the most out of TypeScript, this workshop is for you! In this interactive workshop, we will explore the use of advanced types to improve the safety and predictability of your TypeScript code. You will learn when to use types like unknown or never. We will explore the use of type predicates, guards and exhaustive checking to make your TypeScript code more reliable both at compile and run-time. You will learn about the built-in mapped types as well as how to create your own new type map utilities. And we will start programming in the TypeScript type system using conditional types and type inferring.
Are you familiar with the basics of TypeScript and want to dive deeper? Then please join me with your laptop in this advanced and interactive workshop to learn all these topics and more.
You can find the slides, with links, here:
http://theproblemsolver.nl/docs/ts-advanced-workshop.pdf
And the repository we will be using is here:
https://github.com/mauricedb/ts-advanced