Create and Render Blog Articles in Storyblok and Nuxt
Storyblok is the first headless CMS that works for developers & marketers alike.
In this part, we’ll add a blog to our website. More specifically, we’ll include featured articles on the home page and an overview of all articles on a dedicated blog page. Along the way, you’ll learn many exciting things, including how to create and manage folders in Storyblok, how to reference stories in a multi-options field and how to resolve relations using the Storyblok Content Delivery API. Are you ready? Let’s get started!
If you’re in a hurry, have a look at our live demo in Stackblitz! Alternatively, you can explore or fork the code from the Nuxt Ultimate Tutorial GitHub Repository.
Requirements
This tutorial is part 5 of the Ultimate Tutorial Series for Nuxt. We recommend that you follow the previous tutorials before starting this one.
Creating a new Content Type Block for the Blog Articles
First of all, we need to consider how we would like to manage our blog articles. As of right now, we have just one content type block: the page
block for all of our pages. This particular block allows for a lot of flexibility in arranging nested blocks exactly how a content creator might need them in a variety of different use cases. However, when it comes to blog articles, we most likely need less flexibility and more coherency instead. Therefore, we need to consider what a blog article would typically consist of and how that would translate to our selection of Storyblok fields. Let’s go for the following fields:
image
: field type Asset {1}title
: field type Text {2}teaser
: field type Textarea {3}content
: field type Richtext {4}
Alright, so let’s create our new content type block - let’s call it article
:
Managing all Articles from a Dedicated Folder
In order to keep everything nice and tidy, Storyblok makes it easy for you to manage all of your content in folders. Let’s create a new folder called Blog to organize all of our blog articles. When creating a new folder, you can even choose to set the default content type, so we can employ article
block we just created {1}:
Now you can click on the fresh new folder and whenever you create a new story, it will be of the type article
by default.
Once you’ve created the first article, you’ll see the schema we set up in action:
At this point, I would suggest creating 3-4 articles with some dummy content so that we actually have some articles to choose from later on.
Creating a Nested Block for Featured Articles
Having taken care of the block schema for our articles, we can now move on and create a new nested block called popular-articles
. This will be used to choose up to three articles that should be displayed in a preview format. For that block, we need to define the following fields:
headline
: field type Text {1}articles
: field type Multi-Options {2}
Let’s create it:
For the articles
field, we need to take some additional steps to configure it properly. First of all, we have to select Stories as the Source of our available options {1}. Since it should not be possible to select just any story, we can now take advantage of the Blog folder we set up earlier. Simply set blog/
as a value for Path to folder of stories {2}. Additionally, we should make sure only stories of the content type article
are included in the options to choose from {3}. Finally, let’s limit the maximum number of articles that can be selected to 3
{4}.
Once you’ve created this block, you can use it anywhere on the Home story (at the root level of the content section in the Storyblok Space) and select up to three of your previously created articles.
Creating a Nested Block for All Articles
This nested block is needed to display previews of all existing articles at once. It is fairly straightforward to set up: all that is needed is a new nested block by the name all-articles
with one text field called headline
. The logic to retrieve all articles will be implemented in the frontend.
Once created, this block should be added on the Home story in our Blog folder, where it will serve to render an overview of all blog articles.
Adapting the Nuxt Project
Fantastic, we’re done with everything we need to configure on the Storyblok side of things - now let’s dive into the code, shall we?
Rendering Single Articles
Now we can create a new component that renders the single view of our articles:
Most of this code should be somewhat familiar to you at this point. However, there are two interesting things happening here. First, we are attaching two parameters to the image url (/m/1600x0
), resulting in an optimized, resized image being generated by the Storyblok Image Service. Second, we are resolving the rich text field we created for the main content of our articles. This is achieved using the built-in renderRichText
function of @storyblok/nuxt.
When using TailwindCSS, installing the @tailwindcss/typography plugin and using the prose
class results in beautifully formatted text.
If you open any of your articles in the Visual Editor, everything should be rendered correctly now:
Rendering Popular Articles
Next, let’s create another new component that serves to render the selected popular articles.
As you can see, we are looping through the blok.articles
field using a nested ArticleCard.vue
component. Outsourcing the code for the article cards is quite helpful because we can easily reuse it later for All Articles block.
Since this component exclusively exists in our code base but not in the block library of our space, I would suggest putting it in the components
rather than the storyblok
folder. Except for the article
prop, it should also accept a slug
prop so that we can pass the article story’s full_slug
value and use it in our template. Using NuxtLink
, we can now link each of these article cards to the full article view. Let’s create the article card component:
Resolving Relations to Retrieve the Popular Articles
Now there’s just one more thing we need to take care of in order to have our Popular Articles block render correctly. Right now, the articles
field of our block would only include the uuids
of the stories (blog articles) we referenced. By default, the Storyblok Content Delivery API would only return the data of the main story you are requesting (which would be the Home story in this case, as that is where we included the Popular Articles block earlier). However, using a really convenient API parameter called resolve_relations
, we can retrieve the data of the stories we referenced, too.
In order to do that, we have to specify the block and the field containing the uuids
that should be resolved. We can easily make that change in our […slug.vue]
:
As you can see, we’re passing the array of relations to be resolved twice: first for the API request, and then for the Storyblok Bridge. To learn more about how that works, you can head over to the @storyblok/js documentation.
You can experiment with the resolve_relations
parameter by opening the Draft JSON in a new tab and attaching the parameter to the URL, e.g. &resolve_relations=popular-articles.articles
. Resolved stories will be shown in a rels
array at the end of the JSON response.
Wonderful, now our popular articles should show up correctly:
Rendering All Articles
Finally, we also have to create a component that renders all articles:
In the template section, it is very similar to storyblok/PopularArticles.vue
. However, there is something odd going on in the script section. No worries, let’s go through it together!
Up until now, we’ve always requested a single story from the API. Here, using cdn/stories
, we’re requesting multiple stories. To narrow down our results, we’re employing the starts_with
parameter. In this particular case, we’re telling the API to deliver all stories that exist in our Blog folder. Also, we want to make sure that our Blog Home page is not included. Since it is defined as the root for the folder, we can easily exclude it by setting the is_startpage
parameter to false
.
Having taken care of that, we can just reuse our ArticleCard.vue
component to loop through our articles and pass on all relevant properties.
And just like that, all of our articles should render correctly in the blog overview page:
Wrapping Up
Congratulations, you’ve completed yet another crucial step on your way to becoming a Storyblok and Nuxt expert! By now, you have successfully integrated a blog into your website and took a deeper dive into the Storyblok CMS and its Content Delivery API. While there’s still so much to discover, I hope that the concepts we explored together in this part already help you to gain a more thorough understanding of the workings of Storyblok and how to use these to you advantage when developing your own projects in the future.
The next part, exploring how to manage multilingual content in Storyblok and Nuxt, is already available!
Resource | Link |
---|---|
Storyblok Nuxt 3 Ultimate Tutorial | https://www.storyblok.com/tp/storyblok-nuxt-ultimate-tutorial |
Storyblok Nuxt 3 Module | https://github.com/storyblok/storyblok-nuxt |
Storyblok Nuxt Technology Hub | https://www.storyblok.com/tc/nuxtjs |
Storyblok APIs | https://www.storyblok.com/docs/api |
Nuxt 3 | https://v3.nuxtjs.org/ |