⚠️Draft Content

Storyblok Raises $80M Series C - Read News

What’s the True Total Price of Enterprise CMS? Find out here.

Skip to main content

Managing Redirects with a Headless CMS

Try Storyblok

Storyblok is the first headless CMS that works for developers & marketers alike.

In this tutorial, we’ll explore how to conveniently manage your redirects using a headless CMS. Specifically, we’ll cover how to create a content model that allows you to manage your redirects conveniently from a single story in your Storyblok space. Moreover, we’ll consider how the redirects data can be utilized in your frontend. With this suggested content model solution for redirects, you can save time and effort while ensuring that your users have a seamless experience on your website. So, let's dive in and explore redirects management using Storyblok!

Creating the component schema

In order to manage all of our redirects conveniently, we can use a single story that stores all of the relevant information. This approach has the additional benefit of only requiring a single API call later when implementing the data in a frontend framework.

Therefore, in a newly created blank space, let’s start by creating a new Content type block with the technical name redirects_config.

Creating a new content type block

Creating a new content type block

Herein, we can create a new field of the type Blocks and call it redirect_entries.

Creating a new Blocks field

Creating a new Blocks field

Next, let’s create a new Nestable block of the name redirect_entry. Having created it, we now need to define two new fields. The first should be a Text field called source_url. This is where we can later provide a URL that should be redirected from.

Creating a new Text field

Creating a new Text field


HINT:

If you want another layer of bulletproofing or control, you could use the field’s Regex validation to prevent incorrect entries.

Only having a source URL will only get us so far, though. Therefore, let’s define another new field. This one should be a Single-option field called target_story. At this point, you may be wondering why we chose different field types for the source and the target. While you could also use a Text field for the target, using a Single-option field has the big advantage that it allows us to always fetch the most up-to-date URL by referencing a story. That means that if the URL of any of your stories changes in the future, you won’t have to update all of your existing redirects.

Creating a new Single-option field

Creating a new Single-option field

Let’s set the Source of the target_story field to Stories for this to work {1}.

Setting the source to Stories
1

Setting the source to Stories


HINT:

You can adapt the redirect_entry block’s schema to your liking or requirements. For example, you could also add another field to allow choosing from different HTTP redirect codes.

Finally, we need to go back to the configuration of the redirect_entries Blocks field in our redirects_config Content type block. Here, it is important to check the option to Allow only specific components to be inserted and select the previously created redirect_entry nestable block {1}.

Allowing only specific components to be inserted
1

Allowing only specific components to be inserted

And with that, we’re already done with setting up the schema! Now let’s put it to use.

HINT:

It’s a good idea to restrict access so that only approved users can manage the redirects of your website. You can use Storyblok’s Roles and Permissions feature to granularly control the access according to your requirements.


Managing redirects with a single story

Having created the relevant component schema, we can now create a new story with the name Redirects {1}. It is important to select the previously created content type here {2}.

1
2

When you open that story, you may want to disable the Visual Editor. This particular story should be excluded from the frontend anyway, as it strictly serves as a data point that requires no visual feedback. Now, you can conveniently enter and edit all of your redirects from a single, central location. Let’s create an example redirect by clicking on Add Block {1}.

Adding a new Redirect Entry
1

Adding a new Redirect Entry

We can configure it by entering a source URL such as /example-redirect and picking the Home story as the target story.

Configuring an example redirect

Configuring an example redirect

And just like that, you created your first redirect in Storyblok! Feel free to add further redirects and experiment with the setup. Next, we’ll consider how this data can be used.

Accessing and implementing your redirects

The core idea behind using a single story is that you can make a single API request in order to obtain the data to generate static redirects, be it using a specific framework-native solution or by generating a redirects file for a hosting provider such as Netlify.

You can view your redirects data by opening the Draft or Published JSON {1} of the Redirects story.

Accessing the Redirects JSON
1

Accessing the Redirects JSON

In the JSON response, you’ll find the redirect_entries array nested in the content object of the story object, looking similar to this:

        
      "redirect_entries": [
  {
    "_uid": "aca855c8-0aa1-4702-ac2f-18c026781cfb",
    "component": "redirect_entry",
    "source_url": "/example-redirect",
    "target_story": "077c6f31-a496-41bf-975b-1bac17fbade6"
  },
  {
    "_uid": "71785b9b-99fa-48e8-baac-e2bac613aaac",
    "component": "redirect_entry",
    "source_url": "/another-example-redirect",
    "target_story": "077c6f31-a496-41bf-975b-1bac17fbade6"
  }
]
    

As you can see, the target_story values aren’t particularly useful at the moment. That is the case because we need to resolve these stories. We can accomplish that by adding the parameter to the URL in your browser’s address bar: &resolve_relations=redirect_entry.target_story. Now you’ll find all of the relevant data in the rels array of the JSON response.

Fortunately, using the Storyblok Universal JavaScript Client makes our lives quite a bit easier, as it directly injects the resolved data.

Here’s an example request using the JavaScript Client:

        
      let Storyblok = new StoryblokClient({
  accessToken: 'YOUR_SPACE_ACCESS_TOKEN',
  cache: {
    clear: 'auto',
    type: 'memory',
  },
})

Storyblok.get('cdn/stories/redirects', {
  version: 'draft',
  resolve_relations: 'redirect_entry.target_story',
})
    

HINT:

You could trigger the regeneration of your static redirects by employing a Storyblok webhook (using the Story published trigger) or using the Task Manager App.


A short case study using Astro

Let’s walk through a quick example using Astro in order to illustrate how to implement the redirects data in a practical context. You can kickstart a new Storyblok and Astro project in a matter of minutes following these instructions.

Looking at Astro’s Redirects Documentation, we need to provide a simple object. In our boilerplate project created from the steps above, we can accomplish that by creating a short helper function in which the Redirects story is fetched and the array is then processed into an object that’s compatible with the Astro configuration. Let’s first install the JavaScript client by running npm i storyblok-js-client and then create the file src/functions/getRedirects.js:

src/functions/getRedirects.js
        
      import StoryblokClient from 'storyblok-js-client'

export default async function () {
  let Storyblok = new StoryblokClient({
    accessToken: 'YOUR_SPACE_ACCESS_TOKEN',
    cache: {
      clear: 'auto',
      type: 'memory',
    },
  })

  const { data } = await Storyblok.get('cdn/stories/redirects', {
    version: 'draft',
    resolve_relations: 'redirect_entry.target_story',
  })

  const redirects = data.story.content.redirect_entries

  let processedRedirects = {}

  for (const redirect of redirects) {
    const targetUrl = redirect.target_story.full_slug === 'home' ? '/' : `/${redirect.target_story.full_slug}`
    processedRedirects[redirect.source_url] = targetUrl
  }

  return processedRedirects
}
    

HINT:

In case the target URL is home, we’d like to redirect to / (assuming that the Real path of your Home story is set to to /, too).

Now we can import this function in our Astro configuration and use top-level await to receive the object containing all of the redirects defined in our Storyblok space. Thanks to some syntactic sugar, we can add this information to the configuration quite elegantly:

astro.config.mjs
        
      import { defineConfig } from 'astro/config'
import storyblok from '@storyblok/astro'
+ import getRedirects from './src/functions/getRedirects'

+ const redirects = await getRedirects()

export default defineConfig({
+  redirects,
  integrations: [
    storyblok({
      accessToken: '<your-access-token>',
      components: {
        page: 'storyblok/Page',
        feature: 'storyblok/Feature',
        grid: 'storyblok/Grid',
        teaser: 'storyblok/Teaser',
      },
    }),
  ],
})
    

HINT:

Although we use the @storyblok/astro SDK, we need to additionally install storyblok-js-client, because the redirects data needs to be fetched before the SDK is even initialized.

That’s it! You can launch your project by running npm run dev. If you’ve followed the tutorial, the previously set up redirect should now work: https://localhost:3000/example-redirect will redirect you to https://localhost:3000. The process will be very similar when using any other modern JavaScript frontend framework.

Learn:

When you are generating the site statically make sure to exclude the Redirect Story.

Wrapping Up

Congratulations! In this tutorial, you learned how create and customize a content model to manage your redirects as well as how this dataset can be used and implemented.

Author

Manuel Schröder

Manuel Schröder

A former International Relations graduate, Manuel ultimately pursued a career in web development, working as a frontend engineer. His favorite technologies, other than Storyblok, include Vue, Astro, and Tailwind. These days, Manuel coordinates and oversees Storyblok's technical documentation, combining his technical expertise with his passion for writing and communication.