@storyblok/nuxt (Version 8.x)
@storyblok/nuxt is Storyblok’s official development for Nuxt applications.
Requirements
Section titled “Requirements”- Nuxt version 3.0 or later
- Node.js LTS (version 22.x recommended)
- Modern web browser (e.g., Chrome, Firefox, Safari, Edge – latest versions)
Installation
Section titled “Installation”Add the package to a project by running this command in the terminal:
npm install @storyblok/nuxt@latestConfiguration
Section titled “Configuration”Import and initialize the SDK using the access token of a Storyblok space.
import { defineNuxtConfig } from "nuxt";
export default defineNuxtConfig({ modules: [ [ "@storyblok/nuxt", { accessToken: "YOUR_ACCESS_TOKEN", apiOptions: { region: "eu", }, }, ], ],});Components
Section titled “Components”Create a Nuxt component for each block defined in Storyblok. Each component will receive a blok prop, containing the content of the block.
<script setup> defineProps({ blok: Object });</script>
<template> <div v-editable="blok"> <h2>{blok.headline}</h2> </div></template>Use <StoryblokComponent> to automatically render nested components.
<script setup> defineProps({ blok: Object });</script>
<template> <main> <StoryblokComponent v-for="currentBlok in blok.body" :key="currentBlok._uid" :blok="currentBlok" /> </main></template>Fetching and rendering
Section titled “Fetching and rendering”In a Nuxt page or component, use the one-liner composable useAsyncStoryblok to fetch a story and render the content with the StoryblokComponent element.
<script setup> const { story } = await useAsyncStoryblok("home", { // asyncData options https://nuxt.com/docs/api/composables/use-async-data#params lazy: false, api: { version: "draft", resolve_relations: "featured-articles.posts", }, bridge: { resolveRelations: ["featured-articles.posts"], }, });</script>
<template> <StoryblokComponent v-if="story" :blok="story.content" /></template>storyblok
Section titled “storyblok”Updated in 8.2.0
Import and initialize the SDK to access and configure all features.
import { defineNuxtConfig } from "nuxt";
export default defineNuxtConfig({ modules: [["@storyblok/nuxt", OPTIONS]],});Alternative syntax:
import { defineNuxtConfig } from "nuxt";
export default defineNuxtConfig({ modules: ["@storyblok/nuxt"], storyblok: OPTIONS,});All options listed in the @storyblok/vue reference are available. The following additional options are available:
| Key | Description | Type |
|---|---|---|
componentsDir | Define a custom directory other than storyblok as the location of components. | string |
enableServerMode | Enables the JavaScript client to be used on the Nitro API server (and disables it from being used client-side). Defaults to false. | boolean |
enableSudoMode | See example below. | boolean |
Example: enableSudoMode
Section titled “Example: enableSudoMode”Use it to apply your custom API customizations.
import { apiPlugin, StoryblokVue } from '@storyblok/vue';
export default defineNuxtPlugin(({ vueApp }) => { vueApp.use(StoryblokVue, { accessToken: '<access-token>', enableSudoMode: true, apiOptions: { cache: { type: 'custom', custom: { flush() { console.log('done'); } } } }, use: [apiPlugin] });StoryblokVue
Section titled “StoryblokVue”Import and use StoryblokVue to create a custom Nuxt plugin as shown in the enableSudoMode example above.
useAsyncStoryblok
Section titled “useAsyncStoryblok”Using this one-liner composable, enable both data fetching and bridge capabilities. This is the recommended option, as it supports both server-side rendering (SSR) and static site generation (SSG).
<script setup> const { story, error } = await useAsyncStoryblok(URL, API_OPTIONS, BRIDGE_OPTIONS);
if (error.value) { throw createError({ statusCode: error.value.statusCode, statusMessage: error.value.statusMessage }); } }</script>For the API_OPTIONS, see the storyblok-js-client reference. For the BRIDGE_OPTIONS, see the @storyblok/preview-bridge reference.
useStoryblok
Section titled “useStoryblok”Enable both data fetching and bridge capabilities using this composable. Recommended only for client-side rendering (CSR).
<script setup> import {useStoryblok} from '@storyblok/vue'; const {(story, fetchState)} = await useStoryblok(URL, API_OPTIONS, BRIDGE_OPTIONS);</script>For the API_OPTIONS, see the storyblok-js-client reference. For the BRIDGE_OPTIONS, see the @storyblok/preview-bridge reference.
useStoryblokApi
Section titled “useStoryblokApi”useStoryblokApi() returns the client instantiated in the application.
<script setup> import { useStoryblokApi } from "@storyblok/nuxt"; const storyblokApi = useStoryblokApi(); const { data } = await storyblokApi.get(URL, API_OPTIONS);</script>For the API_OPTIONS, see the storyblok-js-client reference.
serverStoryblokClient
Section titled “serverStoryblokClient”Introduced in 8.2.0
Get an instance of the Storyblok client for Nitro API Server endpoints with the explicit import #storyblok/server.
import { serverStoryblokClient } from "#storyblok/server";
export default defineEventHandler(async (event) => { const storyblokApi = serverStoryblokClient(event);
const { data } = await storyblokApi.get("cdn/stories/home", { version: "draft", });
return { story: data.story };});useStoryblokBridge
Section titled “useStoryblokBridge”useStoryblokBridge() activates the Storyblok Bridge.
<script setup> import { useStoryblokApi, useStoryblokBridge } from "@storyblok/nuxt";
const storyblokApi = useStoryblokApi(); const { data } = await storyblokApi.get(URL, API_OPTIONS);
onMounted(() => { useStoryblokBridge(STORY_ID, CALLBACK, BRIDGE_OPTIONS); });</script>For the BRIDGE_OPTIONS, see the @storyblok/preview-bridge reference.
StoryblokComponent
Section titled “StoryblokComponent”This component automatically renders Storyblok blocks for corresponding Vue components registered in the application. It requires a blok property. Any additional passed properties are forwarded to the Vue component.
<StoryblokComponent :blok="story.content" />Use it to iterate over blocks fields as follows:
<StoryblokComponent v-for="currentBlok in blok.body" :key="currentBlok._uid" :blok="currentBlok" />v-editable
Section titled “v-editable”Use the v-editable directive in components to connect them to the Storyblok Bridge.
<script setup> defineProps({ blok: Object });</script>
<template> <section v-editable="blok"> <h3>{{ blok.name }}</h3> </section></template>StoryblokRichText
Section titled “StoryblokRichText”Used to render a rich text field from a story.
<StoryblokRichText :doc="blok.richtext_field" />See the @storyblok/richtext reference for further details.
Example: Override default resolvers
Section titled “Example: Override default resolvers”<script setup> import { NuxtLink } from '#components'; import type { StoryblokRichTextNode } from '@storyblok/vue'; import CodeBlok from "./components/CodeBlok.vue";
const resolvers = { // NuxtLink example: [MarkTypes.LINK]: (node: StoryblokRichTextNode<VNode>) => h(NuxtLink, { to: node.attrs?.href, target: node.attrs?.target, }, node.text), // Custom code block component example: [BlockTypes.CODE_BLOCK]: (node: Node) => { return h(CodeBlock, { class: node?.attrs?.class, }, node.children) }, }</script>
<template> <StoryblokRichText :doc="blok.richtext_field" :resolvers="resolvers" /></template>useStoryblokRichText
Section titled “useStoryblokRichText”Use this composable to programmatically render a rich text field.
<script setup> import { useStoryblokRichText } from "@storyblok/nuxt"; const { render } = useStoryblokRichText(RICH_TEXT_OPTIONS);
const content = render(blok.articleContent);</script>
<template> <div v-html="content"></div></template>See the @storyblok/richtext reference for further details.
Example: Override default resolvers
Section titled “Example: Override default resolvers”<script setup> import CodeBlok from "./components/CodeBlok.vue";
const { render } = useStoryblokRichText({ resolvers: { // NuxtLink example: [MarkTypes.LINK]: (node: StoryblokRichTextNode<VNode>) => h(NuxtLink, { to: node.attrs?.href, target: node.attrs?.target, }, node.text), // Custom code block component example: [BlockTypes.CODE_BLOCK]: (node: Node) => h(CodeBlock, { class: node?.attrs?.class, }, node.children) } });
const root = () => render(blok.articleContent);</script>Further resources
Section titled “Further resources”Previous versions
Section titled “Previous versions”Get in touch with the Storyblok community