---
title: Integrate Vue with Storyblok
description: This guide walks you through integrating Storyblok as a headless CMS, fetching content, and building components to render it effectively in your Vue project.
url: https://storyblok.com/docs/guides/vue
---

# Integrate Vue with Storyblok

Use Storyblok to manage the content of your Vue project.

> [!NOTE]
> This guide has been tested with the following package versions::
> 
> -   `vue@3.5.13`
> -   `vue-router@4.5.0`
> -   `@storyblok/vue@8.2.2`
> -   Node.js v22.13.0

## Setup

Create a new Vue project in a few simple steps by following the [Quick Start](https://vuejs.org/guide/quick-start) page from its official documentation.

> [!WARNING]
> Use the `npm create vue` command and opt-out of all optional add-ons.

If you already have a Storyblok account, visit [app.storyblok.com](http://app.storyblok.com/#/signup) or [log in with GitHub](https://github.com/login?client_id=Iv23liC8pLXD6VcT2EbS&return_to=%2Flogin%2Foauth%2Fauthorize%3Fclient_id%3DIv23liC8pLXD6VcT2EbS%26redirect_uri%3Dhttps%253A%252F%252Fapp.storyblok.com%252F#/login) to continue.

Create a [new blank space](https://app.storyblok.com/#/me/spaces/new?tab=select-plan) to follow the tutorial from scratch, or start from the [core blueprint](https://app.storyblok.com/#/spaces/new/blueprint?blueprintReference=starter).

[Create one and start a free Storyblok space](https://app.storyblok.com/#/signup) No Storyblok account yet?

## Installation

In your terminal, `cd` into your Vue project and install the `@storyblok/vue` package.

```bash
npm install @storyblok/vue
```

In the root of your project, create a `.env` file with the access token from your space.

```bash
VITE_STORYBLOK_DELIVERY_API_TOKEN="fqc3tdIuC8djNwEYl5cE5Att"
```

> [!TIP]
> Learn how to get an [access token](https://www.storyblok.com/docs/concepts/access-tokens#space-access-token) for your Storyblok project.

Replace the content of the `main.js` with the one below:

src/main.js

```javascript
import { createApp } from 'vue';
import { StoryblokVue, apiPlugin } from '@storyblok/vue';
import App from './App.vue';

const app = createApp(App);

app.use(StoryblokVue, {
  accessToken: import.meta.env.VITE_STORYBLOK_DELIVERY_API_TOKEN,
  apiOptions: {
    region: 'eu', // Choose the correct region from your Space.
  },
  use: [apiPlugin],
});

app.mount('#app');
```

> [!WARNING]
> Ensure to set the correct `region` value depending on the server location of your Storyblok space. Learn more in the [@storyblok/js package reference](https://www.storyblok.com/docs/libraries/js/js-sdk).

The Storyblok plugin will make features like fetching, components registration and bridge available across your project.

## Fetch a single story

Create a `Home.vue` file, with the `useStoryblokApi` get a client instance to fetch a story’s data.

src/Home.vue

```html
<script setup>
import { useStoryblok } from '@storyblok/vue';

const story = await useStoryblok('home', {
  version: 'draft',
});
</script>

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

This page fetches the home story of your Storyblok space using the convenient `useStoryblok` composable.

The `StoryblokComponent` dynamically renders content type and nestable blocks. In this case, it looks for the content type block of the home story.

> [!TIP]
> This element detects the content type of the story for you, in this case `page` and look for a component of the same name to render the story. Learn more in the [Storyblok Vue package](https://www.storyblok.com/docs/libraries/js/vue-sdk) reference.

Replace the content of the `App.vue` file with the following to render the home view.

src/App.vue

```html
<script setup>
import Home from './Home.vue';
</script>

<template>
  <main>
    <Suspense>
      <template #default>
        <Home />
      </template>
    </Suspense>
  </main>
</template>
```

`Suspense` allows the usage of top-level `await` syntax inside scripts, like in the `Home.vue` file to fetch the story data.

> [!NOTE]
> Learn more about the [Suspense](https://vuejs.org/guide/built-ins/suspense) experimental feature.

## Create and register blocks

Create `Page.vue` component to render all stories of the `page` content type, such as the home story.

src/components/Page.vue

```html
<script setup>
defineProps({ blok: Object })
</script>

<template>
  <StoryblokComponent v-for="currentBlok in blok.body":key="currentBlok._uid" :blok="currentBlok" />
</template>
```

Using `StoryblokComponent` iterate through the `body` field and render the blocks in it.

Stories might contain a `body` or similar field which consists of an array with several blocks of custom types (for example, Feature, Teaser, Grid) in it.

Create the code for these components as follows.

src/components/Feature.vue

```html
<script setup>
defineProps({blok: Object})
</script>

<template>
  <div class="feature">
    <span>{{ blok.name }}</span>
  </div>
</template>
```

src/components/Teaser.vue

```html
<script setup>
defineProps({ blok: Object })
</script>

<template>
  <div class="teaser">
    <h2>{{ blok.headline }}</h2>
  </div>
</template>
```

src/components/Grid.vue

```html
<script setup>
defineProps({blok: Object})
</script>

<template>
  <div class="grid">
    <StoryblokComponent v-for="currentBlok in blok.columns":key="currentBlok._uid" :blok="currentBlok" />
  </div>
</template>
```

Similar to `Page.vue`, `Grid.vue` iterates over the `columns` block field.

Add all these new components to your app within the `main.js` file.

src/main.js

```javascript
import { createApp } from 'vue';
import { StoryblokVue, apiPlugin } from '@storyblok/vue';
import App from './App.vue';
import Teaser from './components/Teaser.vue';
import Grid from './components/Grid.vue';
import Feature from './components/Feature.vue';

const app = createApp(App);

app.use(StoryblokVue, {
  accessToken: import.meta.env.VITE_STORYBLOK_DELIVERY_API_TOKEN,
  use: [apiPlugin],
});

 app.component('Teaser', Teaser);
 app.component('Grid', Grid);
 app.component('Feature', Feature);
app.mount('#app');
```

Run the server and visit the site in your browser.

```bash
npm run dev
```

## Related resources

[Storyblok's Vue Blueprint Repository](https://github.com/storyblok/blueprint-core-vue)

[@storyblok/vue Package Reference](https://www.storyblok.com/docs/libraries/js/vue-sdk)

[Concept: Blocks](/docs/concepts/blocks)

[Content Delivery API: Retrieve a Single Story](/docs/api/content-delivery/v2/stories/retrieve-a-single-story)

[Vue Docs](https://vuejs.org/guide/introduction.html)

  

## Pagination

-   [Next: Visual Preview in Vue](/docs/guides/vue/visual-preview)
