Add a headless CMS to VueJS in 5 minutes
Storyblok is the first headless CMS that works for developers & marketers alike.
In this short article, we’ll have a look at how we can use data from the Storyblok API with a Vue.js project to create a website. At the end of this article, you will have a Vue.js Application that renders components filled with data from Storyblok.
In case you don’t know what’s a Headless CMS or what Storyblok does, please read first the Storyblok Guide.
Environment Setup
Requirements
To follow this tutorial make sure to meet these requirements:
- Basic understanding of Vue.js and Javascript
- Node.js LTS version
- An account in the Storyblok App
Create a Vue.js project
Let’s use Vue.js version 3 for this tutorial, since it is now the new default.
Following the Vue.js official installation guide, we can create our project using the official Vue project scaffolding tool: create-vue. It’s Vite based and uses all new recommendations, meaning you’ll get an incredible DX. Use it by running:
Let's choose the following options:
- Add TypeScript? No
- Add JSX Support? No
- Add Vue Router for Single Page Application development? No
- Add Pinia for state management? No
- Add Vitest for Unit Testing? No
- Add Cypress for both Unit and End-to-End testing? No
- Add ESLint for code quality? No
Once you install the dependencies and run npm run dev
in the project folder, you’ll see this screen when you open http://localhost:3000 in your browser:
Now, a Storyblok space with sample content has been created. If you open the Home story you will see the Visual Editor on your screen:
Understand what represents Story in our Storyblok Guide.
Enabling the Visual Editor
To see your website in Storyblok Visual Editor you need to set the default environment URL. For that, in your space open Settings > Visual Editor {1} and set the Location field to https://localhost:3000 {2}:
Storyblok v2 requires that your app is served via HTTPS. Luckily, this is very easily achievable by setting the following option in your vite.config.js
and installing the SSL plugin for the localhost certificates @vitejs/plugin-basic-ssl
Now go back to the Home story under the Content section. When you open it, you’ll see the Visual Editor, but you won’t see yet your Vue application in there.
Just open the Entry configuration {1} on the right-hand form, and set the Real Path to “/” {2}. Save, and if you’re still running your Vue app you will see it now in the Visual Editor.
Connecting Vue to Storyblok
First of all, let’s install @storyblok/vue, our official SDK for Vue 3:
The SDK allows you to interact with Storyblok API and enable the real-time editing experience. Let's configure it.
First of all, you need to grab your API token from your space Settings > API-Keys:
Then add the preview API token in a .env
file:
Setting the correct region
Depending on whether your space was created in the EU, the US, Australia, Canada, or China, you may need to set the region
parameter of the API accordingly:
eu
(default): For spaces created in the EUus
: For spaces created in the USap
: For spaces created in Australiaca
: For spaces created in Canadacn
: For spaces created in China
Here's an example of a space created in the US:
Note: For spaces created in the United States or China, the region parameter must be specified.
Displaying Components on the Vue App
The idea when using Storyblok for this case is:
- A content manager (even if it’s yourself) can create pages (or stories) composed of different sections, called components.
- As a developer, you get the page as a JSON structure using Storyblok API and render the components (which you have to implement in your Vue App).
When you create a space, Storyblok creates 4 components by default for you:
- feature (nestable component)
- grid (nestable component)
- teaser (nestable component)
- page (content type)
You can find them all in the Components section of your Storyblok space.
Understand the difference between the nestable components and content type in our Structures of Content tutorial.
Create Vue Components
Let’s implement the previous 4 components in your Vue App, right under the components folder.
You can see in their template that the Teaser.vue component has a headline
property, and that Feature.vue has a name
.
The question is: how do you know what properties have a blok
? You can check the component schemas to find out.
Finally, make these components available by loading them from main.js:
You can also auto-import all the components under /components
by using this code instead:
Adding TailwindCSS
As you may have noticed, the components we just created utilize Tailwind classes.
Then add the paths of your templates files.
Add the Tailwind directives to your CSS
Load content using the API
Now that we have our components ready, it’s time to get the Home story data. You can view the JSON structure of any story by clicking the Draft JSON button in the Visual Editor.
From the code side, first create a pages/Home.vue component that uses the useStoryblokApi
from @storyblok/vue
to fetch the content:
Now import it in your App.vue. Because we’re using top-level await in Home.vue, you need to use Suspense, a Vue 3 feature that allows you to have control over the asynchronous data flow.
If using vue-router, a RouterView component will be necessary to view all pages within the project. If that's the case, instead of the above code in App.vue you can wrap the router component with Suspense.
At this point, if you navigate to your Home page on Storyblok Visual Editor, you should see the components being rendered successfully.
Real-time editing with Storyblok Bridge
The power of Storyblok relies on its real-time editing experience. Play with changing the teaser headline or re-arranging the features and see the magic happen!
Luckily, @storyblok/vue
makes it very easy for you. In order to make this real-time editing experience possible, your components have to be connected with Storyblok and listen to changes by its Visual Editor. Let's take a closer look at how this is achieved:
First, to link your Vue and Storyblok components together, @storyblok/vue
automatically registers a v-editable
directive. If you check Feature.vue, Grid.vue, and the rest under the components folder, you'll see you already have it there:
Second, @storyblok/vue
loads Storyblok Bridge under the hood and exposes a one-liner useStoryblokBridge
function that you can use to listen for Storyblok Visual Editor changes and update your component state, accordingly.
In our example, we're using the short form syntax by importing useStoryblok
in pages/Home.vue
. This automatically loads Storyblok Bridge and enables it for you!
In case you would like to work with useStoryblokApi
and useStoryblokBridge
separately, you can learn how to accomplish that in our docs on GitHub. Alternatively, you can check out the long form in our live demo.
Wrapping Up
Congrats on reaching this point! You have a Vue 3 app fully connected to Storyblok using its API, bringing a true real-time editing experience.
Can it be even more simple? Yes. Check how to do it with Nuxt.js and find out how our @storyblok/nuxt
module helps by doing some of these steps for you.
If you’re in a hurry, try yourself the live demo in Stackblitz!
We (Storyblok) are huge fans of the Nuxt.js and the Vue.js universe. The Storyblok app is built in Vue.js and we are proud of it. As Nuxt.js is the all-in-one Vue.js meta-framework, we’ve built a Tech Hub to help you with the next steps on your Vue.js and Nuxt.js journey.
Resource | Link |
---|---|
Vue | https://vuejs.org/ |
Storyblok | https://www.storyblok.com/ |
Live Demo | https://stackblitz.com/edit/vue-5-minutes |
Storyblok Vue | https://github.com/storyblok/storyblok-vue |
Storyblok APIs | https://www.storyblok.com/docs/api |
Storyblok Nuxt Technology Hub | https://www.storyblok.com/tc/nuxtjs |