@storyblok/nuxt (Version 7.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@7
Configuration
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", { version: "draft", resolve_relations: "featured-articles.posts" }, { resolveRelations: ["featured-articles.posts"]}, );</script>
<template> <StoryblokComponent v-if="story" :blok="story.content" /></template>
storyblok
Section titled “storyblok”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 |
enableSudoMode | See example below. | boolean |
Example: enableSudoMode
Section titled “Example: enableSudoMode”To include additional functionalities in the apiOptions
, such as custom cache methods, implement the following inside the plugins
folder:
import { apiPlugin, StoryblokVue } from '@storyblok/vue';
export default defineNuxtPlugin(({ vueApp }) => { vueApp.use(StoryblokVue, { accessToken: '<access-token>', apiOptions: { cache: { type: 'custom', custom: { flush() { console.log('done'); } } } }, use: [apiPlugin] });
StoryblokVue
Section titled “StoryblokVue”If desired, import and use StoryblokVue
to create a custom Nuxt plugin as shown in the enableSudoMode example above.
apiPlugin
Section titled “apiPlugin”apiPlugin
configures the implementation of the Storyblok API. It is imported from @storyblok/js
.
import { apiPlugin } from "@storyblok/nuxt";import { defineNuxtConfig } from "nuxt";
export default defineNuxtConfig({ modules: [ [ "@storyblok/nuxt", { accessToken: "<your-access-token>", use: [apiPlugin], }, ], ],});
See the @storyblok/js reference for further details.
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 = await useAsyncStoryblok(URL, API_OPTIONS, BRIDGE_OPTIONS);</script>
<template> <StoryblokComponent v-if="story" :blok="story.content" /></template>
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.
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>
Get in touch with the Storyblok community