Full-fledged CMS systems, like Wordpress, Joomla or Drupal have been around for many years and are still widely used when it comes to creating content heavy websites like blogs, news magazines, etc. They are setup very quickly, can be customized with hundreds of extensions and plugins and provide a thorough authoring experience. However, they also have their downsides of being quite heavyweight, having a tight coupling between frontend and backend and usually are not that fast due to on-demand server-side rendering. Lately, a new era of so called headless CMS systems has gained rapid popularity due to tackling exactly those issues. One of them is Storyblok, which I played around with recently and created the article you are looking right now. Let's take a look at what it takes to setup a convenient blog authoring experience with Storyblok as headless CMS and Nuxt.js as frontend framework.
Creating a page type for articles
We'll start with creating a new reusable blok for our articles. If you are not familiar with the concepts of Storyblok I recommend to take a look at their documentation before reading on because I won't provide a basic introduction to Storyblok here.
As you can see in the config of our blok we mark it as content type instead of nestable because we want our article as standalone block.
We define some metadata as shown in the second screenshot, whereby the important attribute is the full_text
which is of type Richtext and provides the content of our article. Keep in mind that this is not plain text but can also contain images, code blocks, bullet lists, etc. We want to render this as HTML finally on our page.
Creating the respective component in Nuxt.js
So far our blok exists in our Storyblok backend but nothing on our webpage presents it until now. In order to solve this, we need to create a new Vue component in our Nuxt project.
<template>
<div v-editable="blok" class="max-w-3xl p-2 mt-4 mx-auto">
<article>
{{ blok.content.full_text }}
</article>
</div>
</template>
<script>
export default {
props: {
blok: {
type: Object,
required: true,
},
},
}
</script>
This Vue component gets passed a specific article as prop and then injects the richtext in the article HTML tag. When rendering a particular article we'll see the richtext on the page but not the way we want. The text is just shown with all HTML entities. This makes sense as we don't do anything to handle the HTML richtext.
Storyblok Richtext Vue Renderer
Thanks to Marvin Rudolph there is a nice Vue plugin for rendering richtext in Vue based frontends. We can use it by doing following steps:
Installing
npm install @marvr/storyblok-rich-text-vue-renderer
npm install @vue/composition-api
Registering as Vue plugin
In order to register a Vue plugin, running before instantiating the root Vue.js application, in a Nuxt project, we create a JavaScript file in the plugins directory. There we register the rich-text-renderer.
import Vue from 'vue'
import VueRichTextRenderer from '@marvr/storyblok-rich-text-vue-renderer'
Vue.use(VueRichTextRenderer);
Since the plugin needs the composition API of Vue 3, we need to register this as well. At the time of writing this article Nuxt.js still uses Vue 2 under the hood. That's why we need to do this.
import Vue from 'vue'
import VueCompositionApi from '@vue/composition-api'
Vue.use(VueCompositionApi)
After that we need to tell Nuxt.js about these plugins in our nuxt.config.js
plugins: [
'~/plugins/composition-api.js',
'~/plugins/rich-text-renderer.js'
],
Using it in our component
As the plugins are registered we can now use the renderer in our component from before. Therefore we just need to adapt our article
tag like this:
<article>
<rich-text-renderer :document="blok.content.full_text" />
</article>
As a result we should see the rendered richtext with correct paragraphs, lists, images and whatever else we use in our articles.
Improve style and formatting
Although our article does not contain any HTML entities anymore, it's most likely still not that satisfying how it looks like. Until now we just rely on the default styles of the HTML we render, which is not optimal for every element. Thus, we need to apply some CSS to makes it look nicer. Instead of doing the straightforward but more time-consuming way I want to show you how to use Tailwind's typography plugin for this.
Installing and configuration
Assuming that we have installed Tailwind CSS, we need to install the plugin additionally with npm install @tailwindcss/typography
.
After that we just need to add it as a plugin to our tailwind.config.js
.
plugins: [require('@tailwindcss/typography')],
Applying it
In order to apply it, we simply need to add the classes to our article.
<article class="prose lg:prose-lg">
<rich-text-renderer :document="blok.content.full_text" />
</article>
The prose class is the default one. There are variations for the font sizes you can use. In this example we use a larger set for larger screen sizes. If we now refresh, our article appears in a nicely formatted layout with sensible defaults for things like code blocks.