Storyblok Logo

@storyblok/nuxt-2

Nuxt 2 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 2. Check out @storyblok/nuxt for Nuxt 3.

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-2:

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

Initialize the module by adding it to buildModules section of nuxt.config.js and replace the accessToken with API token from Storyblok space:

{
  buildModules: [
    // ...
    ["@storyblok/nuxt-2/module", { accessToken: "<your-access-token>" }],
  ];
}

Options

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

// Defaults
["@storyblok/nuxt-2/module", {
  {
    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. If you use Nuxt 2.13+, you can just place them on the ~/components/storyblok directory, otherwise you can load them globally (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 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

To use Nuxt 2 with Composition API, make sure you installed the @nuxtjs/composition-api plugin.

The simplest way is by using the useStoryblok one-liner composable, which uses the useFetch from @nuxtjs/composition-api under the hood:

<script setup>
  import { useStoryblok } from "@storyblok/nuxt-2";
  const { story, fetchState } = 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>
  import { onMounted, ref, useFetch } from "@nuxtjs/composition-api";
  import { useStoryblokBridge, useStoryblokApi } from "@storyblok/nuxt-2";

  const story = ref(null);

  const { fetch } = useFetch(async () => {
    const storyblokApi = useStoryblokApi();
    const { data } = await storyblokApi.get(`cdn/stories/vue/test`, {
      version: "draft",
    });
    story.value = data.story;
  });
  fetch();

  onMounted(async () => {
    if (story.value && story.value.id)
      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-2 and a Vue computed property:

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

<script setup>
  import { computed } from "@nuxtjs/composition-api";
  import { renderRichText } from "@storyblok/nuxt-2";

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

Options API

You can still use the useStoryblokApi and useStoryblokBridge as follows:

<script>
  import { useStoryblokBridge, useStoryblokApi } from "@storyblok/nuxt-2";

  export default {
    asyncData: async ({ app }) => {
      const storyblokApi = useStoryblokApi();
      const { data } = await storyblokApi.get("cdn/stories/vue", {
        version: "draft",
      });
      // OR: const { data } = await app.$storyapi.get("cdn/stories/vue", { version: "draft" });

      return { story: data.story };
    },
    mounted() {
      useStoryblokBridge(this.story.id, (newStory) => (this.story = newStory));
    },
  };
</script>

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

As you see in the comment, you can also use app.$storyapi if that's more comfortable for you. It's injected into Nuxt context and available in the components instance via this.$storyapi as well.

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.

$storyapi

Equivalent to the client that useStoryblokApi returns, but accessible in the Nuxt context and components instance.

🔗 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.