# Usage

Vue Storefront comes with the great public API (opens new window) that allows you to connect and integrate with any content delivery/management system. Usually using this API leads to connection with CMS JavaScript SDK that can be used as a bridge to build a universal data structure for content rendering.

Therefore, this Storyblok integration provides composition functions called composables which use mentioned connection. Below you can find detailed instructions on how to use those composables along with your application. Don't worry it's quite straightforward.

CMS Integration

You can read more about CMS integration process here (opens new window).

Now, import useContent composable to fetch and display the content from the Storyblok.

import { useContent } from '@vue-storefront/storyblok'

By using search method from the useContent composable you can get data from the previously created (in the Storyblok panel) component or story.

const { search, content, loading, error } = useContent('unique-id')
// run search() with url argument
await search({ url: 'home-page' })
// then you can get the content
return content

# Content Rendering

First, copy the special RenderContent.vue component from the integration package.

cp node_modules/@vue-storefront/storyblok/components/RenderContent.vue cms/

As a next step, you have to register your components. You can do this in two ways:

  • adding components to the RenderContent.vue component,
  • registering components globally.

To register components globally, create a Nuxt plugin ~/plugins/cms.js like the one shown below and add them. This way, you'll be able to use those components anywhere in the application without importing and registering them individually:

// plugins/cms.js
import Vue from 'vue'
import Banner from '~/cms/Banner.vue'

Vue.component(Banner)
// nuxt.config.js
export default {
  plugins: ['~/plugins/cms'],
}

Finally, you have to pass content data to the RenderContent component as a content prop.

Let's check it with the real life example.

<template>
  <div v-if="loading">Loading content...</div>
  <div v-if="error">Something is wrong!</div>
  <div v-if="content">
    <render-content :content="content" />
  </div>
</template>

<script>
import { onSSR } from '@vue-storefront/core'
import { useContent } from '@vue-storefront/storyblok'
// path to the component that you've just copied
import RenderContent from '~/cms/RenderContent.vue'

export default {
  components: {
    RenderContent
  },
  setup() {
    const { search, content, loading, error } = useContent('unique-id')
    // get data
    onSSR(async () {
      await search({ url: 'home-page' })
    })
    // return data
    return {
      content,
      loading,
      error,
    }
  }
}
</script>

RenderContent component will create the Banner.

<Banner :name="componentName" :props="props" />

Remember to create and define the components with all the props that will be used in. Instead of this you'll get a component registration error. In other words if your data will include components that don't have real representation in the application you'll get an error, and those components will not render. More about: here (opens new window).

You can read about creating components in Storyblok here.

# References / Relations


Storyblok provides ability to refer, link from one content block to another. You can create components that will keep list of ids of these blocks. With that you will be able to create more global and reusable structure for your stories or components. You have two options to handle this feature. By fetching data on the client side - on top of the referred content ids - or by resolving connection from the default Storyblok API.

1) First you need to create Reference component with content field.

2) Define your content relations.

3) Create some content entries in the items folder. You'll be referring to them.

4) Use your Reference component to connect some content with.

Now, as mentioned above, you have two options to handle your references/relations.

1) With Reference component content you'll receive the list of referred content block ids. On top of this list you'll be able to fetch these on the client side. To do that define (in the new Reference.vue component) your search function call like this.

<template>
  <div v-if="content">
    <render-content :content="content" />
  </div>
</template>

<script lang="ts">
import RenderContent from '~/cms/RenderContent.vue'
import { defineComponent } from '@nuxtjs/composition-api'
import { useContent } from '@vue-storefrint/storyblok'

export default defineComponent({
  name: 'Reference',
  components: { RenderContent },
  props: {
    content: {
      type: Array,
    },
  },
  setup(props) {
    const { search, content } = useContent('unique-id')
    // get data by ids
    props.content.map(async (id) => {
      await search({
        id,
        cache: false,
        version: 'draft',
      })
    })
    return {
      content,
    }
  },
})
</script>

With this approach, you have more control over the content that you're fetching from the platform. You can manage the payloads and handle them with some additional logic. The main inconveniently here is that you need to do this on the client-side.

2) Second option is to resolve the content relations using Storyblok's native API. When defining your content fetching, call search method with the relations param. You can find more information about this on the API Reference page.

Here is the real life example.

// Page / Container Component
export default defineComponent({
  setup(props) {
    const { search, content } = useContent('unique-id')
    // get data with all the relationed components
    onSSR(async () => {
      await search({
        cache: false,
        version: 'draft',
        relations: 'Reference.items',
      })
    })
    return {
      content,
    }
  },
})

This way you'll get all the related data inside your Reference component - as the content object. This will be an Array, so you will need to handle this list by iterating them and passing to the RenderContent component.

<template>
  <div v-if="content">
    <render-content v-for="(ref, index) in content" :key="index" :content="ref.content" />
  </div>
</template>

<script lang="ts">
import RenderContent from '~/cms/RenderContent.vue'
import { defineComponent } from '@nuxtjs/composition-api'

export default defineComponent({
  name: 'Reference',
  components: { RenderContent },
  props: {
    content: {
      type: Array,
    },
  },
})
</script>

With this approach, you will get all the data right from the server response. However, you'll get all entries at once. This can cause performance issues if you have a large amount of content.

TIP

References can be used as well as a Storyblok links. Covering the same feature.

More about building relations and content connections you can read here (opens new window).

# Real-time Visual Editor - Storyblok Bridge


IMPORTANT: From version 0.3.0 the Storyblok Bridge v1 is deprecated.

With this feature, you'll be able to manage and preview your content right from the Storyblok panel without publishing it. You can read more about this in Storyblok's documentation (opens new window).

1) Add current Storyblok Bridge from here (opens new window) to your nuxt.config.js like below.

// nuxt.config.js
{
  "modules": [
    "@vue-storefront/storyblok/nuxt",
    {
      "jsBridge": "https://app.storyblok.com/f/storyblok-v2-latest.js"
    }
  ]
}

2) Import a special helper storyblokBridge from the package to initialize Storyblok Bridge.

import { storyblokBridge } from '@vue-storefront/storyblok';

In the onMounted hook, use the function you just imported with the content object as a param. It's important to define the Bridge on the client-side because it's referring to the window object.

Look into another life example.

<template>
  <div v-if="content">
    <render-content :content="content" />
  </div>
</template>

<script>
import { useContent, storyblokBridge } from '@vue-storefront/storyblok'
import { onSSR } from '@vue-storefront/core'
import { computed, onMounted } from '@vue/composition-api'
import RenderContent from '~/cms/RenderContent.vue'

export default {
  name: 'Home',
  components: {
    RenderContent,
  },
  setup() {
    const { search, content } = useContent('unique-id')
    // wrap your content with reactive computed function
    const story = computed(() => content.value)
    // get data
    onSSR(async () => {
      await search({ url: 'home-page' })
    })
    // init the Storyblok Bridge
    onMounted(() => {
      storyblokBridge(story.value)
    })
    return {
      content: story,
    }
  },
}
</script>

More about events you can find here (opens new window).