storyblok-nuxt icon indicating copy to clipboard operation
storyblok-nuxt copied to clipboard

Storyblok Nuxt module

Storyblok Logo

@storyblok/nuxt

Nuxt 3 module for the Storyblok, Headless CMS.


Storyblok JS Client npm

Follow @Storyblok
Follow @Storyblok

Live Demo

If you are in a hurry, check out our official live demo on Stackblitz.

🚀 Usage

Note: This module is for Nuxt 3. Check out @storyblok/nuxt-2 for Nuxt 2.

If you are first-time user of the Storyblok, read the Getting Started guide to get a project ready in less than 5 minutes.

Installation

Install @storyblok/nuxt:

npm install @storyblok/nuxt
# yarn add @storyblok/nuxt

Add following code to modules section of nuxt.config.js and replace the accessToken with API token from Storyblok space.

import { defineNuxtConfig } from "nuxt";

export default defineNuxtConfig({
  modules: [
    ["@storyblok/nuxt", { accessToken: "<your-access-token>" }]
    // ...
  ]
});

You can also use the storyblok config if you prefer:

import { defineNuxtConfig } from "nuxt";

export default defineNuxtConfig({
  modules: ["@storyblok/nuxt"],
  storyblok: {
    accessToken: "<your-access-token>"
  }
});

Options

When you initialize the module, you can pass all @storyblok/vue options plus a useApiClient options:

// Defaults
["@storyblok/nuxt", {
  {
    accessToken: "<your-access-token>",
    bridge: true,
    apiOptions: {}, // storyblok-js-client options
    useApiClient: true
  }
}]

Getting started

1. Creating and linking your components to Storyblok Visual Editor

To link your Vue components to their equivalent you created in Storyblok:

  • First, you need to load them globally. You can just place them on the ~/storyblok directory and will be discovered automagically, otherwise you set another directory can load them manually (for example, by using a Nuxt plugin).

  • For each components, use the v-editable directive on its root element, passing the blok property that they receive:

<div v-editable="blok" / >
  • Finally, use <StoryblokComponent> which is available globally in the Nuxt app:
<StoryblokComponent :blok="blok" />

The blok is the actual blok data coming from Storblok's Content Delivery API.

2. Getting Storyblok Stories and listen to Visual Editor events

Composition API

The simplest way is by using the useStoryblok one-liner composable (it's autoimported) and passing as a first parameter a name of your content page from Storyblok (in this case, our content page name is vue, by default you get a content page named home):

<script setup>
  const story = await useStoryblok("vue", { version: "draft" });
</script>

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

Which is the short-hand equivalent to using useStoryblokApi and useStoryblokBridge functions separately:

<script setup>
  const story = ref(null);
  const storyblokApi = useStoryblokApi();
  const { data } = await storyblokApi.get("cdn/stories/vue", {
    version: "draft"
  });
  story.value = data.story;

  onMounted(() => {
    useStoryblokBridge(story.value.id, (evStory) => (story.value = evStory));
  });
</script>

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

Rendering Rich Text

You can easily render rich text by using the renderRichText function that comes with @storyblok/nuxt and a Vue computed property:

<template>
  <div v-html="articleContent"></div>
</template>

<script setup>
  const articleContent = computed(() => renderRichText(blok.articleContent));
</script>

API

useStoryblok(slug, apiOptions, bridgeOptions)

Check the available apiOptions (passed to storyblok-js-client) and bridgeOptions (passed to the Storyblok Bridge).

useStoryblokApi()

Returns the instance of the storyblok-js-client.

useStoryblokBridge(storyId, callback, bridgeOptions)

Use this one-line function to cover the most common use case: updating the story when any kind of change happens on Storyblok Visual Editor.

🔗 Related Links

ℹī¸ More Resources

Support

Contributing

Please see our contributing guidelines and our code of conduct. This project use semantic-release for generate new versions by using commit messages and we use the Angular Convention to naming the commits. Check this question about it in semantic-release FAQ.