Skip to content

Integrate Nuxt with Storyblok

Use Storyblok to manage the content of your Nuxt application.

Create a new Nuxt project in a few simple steps by following the Installation page from its official documentation.

If you already have a Storyblok account, go to app.storyblok.com or log in with GitHub to continue.

Create a new blank space (opens in a new window) to follow the tutorial from scratch, or start from the core blueprint (opens in a new window).

In the terminal, cd into the Nuxt project and install the @storyblok/nuxt package.

Terminal window
npm install @storyblok/nuxt@3

In the nuxt.config.ts configuration file, add the Storyblok module:

nuxt.config.ts
export default defineNuxtConfig({
devtools: { enabled: true },
modules: [
[
'@storyblok/nuxt',
{
accessToken: process.env.STORYBLOK_DELIVERY_API_TOKEN,
apiOptions: {
region: 'eu',
},
},
],
],
});

In the root of your project, create a .env file with the access token from your space.

.env
STORYBLOK_DELIVERY_API_TOKEN=<YOUR-ACCESS-TOKEN>

The Storyblok module will make features like fetching, component registration, and bridge available across your project.

Remove app.vue and create a new file pages/index.vue with the useAsyncStoryblok to fetch a story’s data.

pages/index.vue
<script setup>
const { story } = await useAsyncStoryblok('home', {
api: {
version: 'draft', // or 'published'
},
});
</script>
<template>
<StoryblokComponent v-if="story" :blok="story.content" />
</template>

The StoryblokComponent dynamically renders content type and nestable blocks. In this case, it looks for the content type block of the home story.

Create a Page.vue component to render all stories of the page content type, such as the home story.

storyblok/Page.vue
<script setup>
defineProps({ blok: Object });
</script>
<template>
<main v-editable="blok">
<StoryblokComponent
v-for="currentBlok in blok.body"
:key="currentBlok._uid"
:blok="currentBlok"
/>
</main>
</template>

Using StoryblokComponent, iterate through the body field and render the blocks in it.

Stories might contain a body or a similar blocks field which consists of an array with several blocks of custom types (e.g., Feature, Teaser, Grid) in it.

Create the code for these components as follows.

storyblok/Feature.vue
<script setup>
defineProps({ blok: Object });
</script>
<template>
<div class="feature">
<span>{{ blok.name }}</span>
</div>
</template>
storyblok/Teaser.vue
<script setup>
defineProps({ blok: Object })
</script>
<template>
<div class="teaser">
<h2>{{ blok.headline }}</h2>
</div>
</template>
storyblok/Grid.vue
<script setup>
defineProps({ blok: Object });
</script>
<template>
<div class="grid">
<StoryblokComponent
v-for="currentBlok in blok.columns"
:key="currentBlok._uid"
:blok="currentBlok"
/>
</div>
</template>

Similar to Page.vue, Grid.vue iterates over the columns block field.

Run the server and visit the site in your browser.

Terminal window
npm run dev