Storyblok Raises $80M Series C - Read News

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

Skip to main content

Render Storyblok Stories Dynamically in Nuxt

Try Storyblok

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

Having successfully integrated Storyblok into our Nuxt app in the last tutorial, let’s know take it one step further and add dynamically rendered pages as well as a page layout.

Live demo:

If you’re in a hurry, have a look at our live demo in Stackblitz! Alternatively, you can explore or fork the code from the Nuxt Ultimate Tutorial GitHub Repository.

Requirements

This tutorial is part 2 of the Ultimate Tutorial Series for Nuxt. We recommend that you follow the previous tutorial before starting this one.

Creating a Layout

Before creating additional pages in Storyblok, let’s first of all create a layout in our Nuxt app. This layout should include a header bar and a primary navigation for our website – because having multiple pages without being able to navigate between them doesn’t make much sense, does it?

So let’s start by creating a header component. Since this won’t have a corresponding blok in our Storyblok space, we’ll create it in the components folder:

components/Header.vue
        
      <template>
  <header class="w-full h-24 bg-[#f7f6fd]">
    <div class="container h-full mx-auto flex items-center justify-between">
      <NuxtLink to="/">
        <h1 class="text-[#50b0ae] text-3xl font-bold">Storyblok Nuxt</h1>
      </NuxtLink>
      <nav>
        <ul class="flex space-x-8 text-lg font-bold">
          <li>
            <NuxtLink to="/blog" class="hover:text-[#50b0ae]">Blog</NuxtLink>
          </li>
          <li>
            <NuxtLink to="/about" class="hover:text-[#50b0ae]">About</NuxtLink>
          </li>
        </ul>
      </nav>
    </div>
  </header>
</template>
    

Now we can implement this header component in our layout. Fortunately, Nuxt allows us to create layouts very easily. All we have to do is to create a default.vue in a layouts folder with the following content:

layouts/default.vue
        
      <template>
  <main>
    <Header />
    <slot />
  </main>
</template>
    

And that’s it! If you take a look at your project running on https://localhost:3000 now, you’ll see your header component:


Nuxt Layout rendered correctly

Nuxt Layout rendered correctly

Rendering Pages dynamically

Before actually creating any new pages in the Storyblok space, let’s take care of the required logic on the frontend side.

Once again, Nuxt makes it extremely easy for you. All we have to do is to delete our pages/index.vue and replace it with a pages/[...slug].vue.

pages/[...slug].vue
        
      <script setup>
const { slug } = useRoute().params

const story = await useAsyncStoryblok(
  slug && slug.length > 0 ? slug.join('/') : 'home',
  { version: 'draft' }
)
</script>

<template>
  <StoryblokComponent v-if="story" :blok="story.content" />
</template>

    

So, what’s happening here? We’re dynamically getting the current slug via the useRoute function. This is then passed as a parameter to the useAsyncStoryblok function. If the slug is empty, we want our Home story to be displayed.

Adding Pages in Storyblok

With our logic being complete, we can now add our Blog and About pages in our Storyblok space! To do that, simply go to Content {1}, Create new {2}, and then Choose Story {3}.

Adding a story
1
2
3

Adding a story

Now you can provide a name {1} – the slug will be filled out automatically for you. Let’s start with the About page.

Configuring a new story
1

Configuring a new story

Once the page is created, you can add nestable bloks to it. Simply click on the Plus Icon {1} and add a Teaser component {2}.

Inserting a new block
1
2

Inserting a new block

Now you can enter any headline you want for your newly created About page:

New block rendering correctly on the About page

New block rendering correctly on the About page

Try to repeat the same process on your own for the Blog page.

Bonus: Highlighting the currently active navigation item

If you click on the navigation entries in our Header component, everything already works as expected. Let’s take it a little further by highlighting the currently active navigation item. Yet again, this is extremely easy to accomplish in Nuxt because it automatically adds a router-link-active class to your links! Let’s utilize it by adding the following styles to the Header component:

components/Header.vue
        
      <style scoped>
nav a.router-link-active {
  @apply underline underline-offset-4 decoration-4 decoration-[#50b0ae];
}
</style>
    

Wrapping Up

Congratulations! You have created your first pages in Storyblok and they are rendered in your Nuxt app dynamically – how cool is that!?

Next Part:

Continue reading and find out How to create Dynamic Menus in Storyblok and Nuxt. Not interested in dynamic menus? Feel free to skip this part and learn How to Create Custom Components in Storyblok and Nuxt.

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.