Nuxt.js & Storyblok CMS as alternative to Jekyll

We redesigned our website! Same design, different technology.

When we developed our previous company website a few years ago, we decided to go for Jekyll. Jekyll is a static site generator that converts markdown into static html pages. It’s fast and can be hosted for free on GitHub Pages. It’s a great tool for blogs and simple pages.

The downside of static site generators like Jekyll is the authoring experience. It lacks a decent WYSIWYG interface where authors can build pages. Popular content management systems like AEM, WordPress and Drupal have, or are moving to a visual interface where authors can start building their website from a blank canvas.

Another evolution in ‘CMS land’ is to decouple content management from the front-end and serve content through API calls (aka Headless Content Management). By decoupling content from your application, content becomes front-end agnostic. It makes it easier to reuse content across different channels. While a lot of traditional/monolithic CMS’s are moving to this headless approach, I noticed there are a lot of new kids on the block.

Storyblok logo

One of these new kids is Storyblok. What I like about Storyblok compared to the other headless CMS’s is their support for a visual editor. Storyblok provides a bridge to communicate between your front-end and their content editor. By adding id’s to your front-end (vue) components, Storyblok knows which component is selected in their visual editor.

Template based vs Component based page architecture

Another thing I like about Storyblok is their focus on a component-based architecture. When choosing a CMS or defining the page architecture within your CMS, you should obviously first analyze your content.

Template vs Component based page design

If you have a lot of content with the same structure, like product pages, a template-based architecture is recommended.

If you want a rich authoring experience, where marketeers can build pages with hero’s, sliders, call to actions and other (rich) components, go for a component-based architecture.

Modern JavaScript frameworks like Vue, React and Angular are all component-based. Storyblok provides a friendly user interface to define the content schemes for these components. Once you have defined components in Storyblok, you can start creating content. The content you enter is accessible via a content delivery API which returns structured json files as source for your front-end application.

Storyblok’s image resizing service

Another thing worth mentioning is Storyblok’s Image Service. Every asset uploaded to Storyblok can be resized on the fly, just by adding some parameters to the image source. You can even change the image format to WebP, a modern image format that provides superior compression for images on the web. Compared to jpg and png, WebP images are smaller in file size while maintaining similar image quality. Browser support for Webp is quite ok and can easily be detected.

Why Nuxt.js is a perfect match

Nuxt logo

The biggest requirement for the front-end framework we were going to use was support for server-side rendering. Not all crawlers, especially social media crawlers, are able to parse JavaScript. Server-side rendering makes sure these crawlers have access to the content they need.

Another benefit of server-side rendering is a faster time to content. The server rendered markup is ready to be displayed without the need of JavaScript. Nuxt.js is a framework built on top of Vue and as you might already guess, its biggest strength is support for server-side rendering. Applications that run both on the client and server are also known as universal applications.

How universal apps work

The initial page request will return server-side rendered html. Once this is downloaded to the browser, JavaScript kicks in and users will experience the benefits of a SPA. When the user navigates, content will be loaded directly from the content api.

Nuxt context

When developing universal applications, it’s likely to run into ‘window is not defined’ errors because the window object is not available on the server-side. To make a developers life easier, Nuxt provides a context with parameters like: process.client & process.server.

Nuxt as a static site generator

Another cool thing about Nuxt is the nuxt generate command. With this command, Nuxt can be used as a static site generator. For every route defined in your pages folder, it will generate an HTML file.

If you want to generate dynamic routes, the generate property in nuxt.config.js can be used.

import axios from 'axios'

export default {
 generate: {
   routes: () => {
     return axios.get('https://my-api/users')
     .then(res => {
       return => {
         return '/users/' +

SEO out of the box!

For sites like, with focus on content, SEO is important. In Nuxt, default meta tags are defined in nuxt.config.js. Page specific meta tags override these default meta tags and can be set using the head method of a page component (fe: pages/about.vue). If you’re into SEO, make sure to read these SEO best practices.

It was fun to experiment with both Storyblok & Nuxt and I would recommend using it as alternative to Jekyll for small content driven websites like Compared to Jekyll, this combo makes content management fun.

Bonus tips: