Hi there!
I'm Arisa, a DevRel from this June living in Germany🇩🇪 (A big announcement is coming this June😏)
I have a free online programming learning community called Lilac, with free hands-on Frontend e-books👩💻
Who is this article for?
- Anyone wants to have a super blazing fast blog app with headless CMS integrated in it😎
- Anyone wants to build headless CMS integrated blog with the easiest way
- Anyone wants to try out Storyblok with Gatsby.js
- Anyone trying Storyblok's Gatsby multilanguage blog tutorial
Storyblok: The Complete Guide to Build a Full-Blown Multilanguage Website with Gatsby.js
This is also relevant tutorial blog post from them👇
Step 1: Create a post content type in Storyblok
Create a folder from Storyblok.
This folder will be a parent of each blog post.
If you already have a component created for a blog post, you can set up like the screenshot above.
If not, you can choose "Add new" and choose "Post".
Check the component type we chose or created before we go further.
It's always good to see the component data architecture in order to fetch later.
The best part is that as long as we choose "Post" content type, Storyblok automatically generates the blueprint for blog posts😎
Step 2: Create blog entry page in Storyblok
Let's move on to create a single blog post page.
Go to "Blog" content type folder, the one we just created.
Click "Entry" to create a blog post entry.
You'll be redirected to a single blog post visual editor screen.
Fill out something to test output for later.
One more prep before we go figure out routing.
Install storyblok-rich-text-react-renderer
to render the rich text content.
Storyblok uses this to render rich text content.
$ yarn add storyblok-rich-text-react-renderer
Step 3: Programmatically create pages from data
Gatsby.js dynamically generates routes for you.
To do that, we can choose from 3 options.
- Define routes in src/pages
- Using the File System Route API
- Using gatsby-node.js 👈 Recommended
We'll use the 3rd option because it dynamically generates pages as we create new blog posts in Storyblok main dashboard.
With this option, editors and writers don't have to ask us to create every single blog post, right?
Option 2 is also possible but still, it creates pages under the pages
directory, same as option 1.
Everything I set up in here is based on Gatsby.js's documentation.
If you're lost, their tutorial bog post is the best place to be back on track👍
By using createPage
action from Gatsby, we can create our blog post pages dynamically.
I recommend everyone to take a look at Gatsby's Routing documentation and Storyblok's gatsby-source-storyblok
GitHub repo README.
Especially, we'll use "Filtering on content type fields" section from Storyblok's gatsby-source-storyblok
GitHub repo README.
storyblok/gatsby-source-storyblok: "Filtering on content type fields"
It's just an example, but it might help to see my case.
-
gatsby-node.js
const path = require('path')
exports.createPages = ({ graphql, actions }) => {
const { createPage } = actions
return new Promise((resolve, reject) => {
const blogPostTemplate = path.resolve('./src/templates/blog-entry.js')
resolve(
graphql(
`{
posts: allStoryblokEntry(filter: {field_component: {eq: "Post"}}) {// 👈 the name of your component name
edges {
node {
id
name
slug
field_component
full_slug
content
}
}
}
}`
).then(result => {
if (result.errors) {
console.log(result.errors)
reject(result.errors)
}
const allPosts = result.data.posts.edges
allPosts.forEach((entry) => {
// 👇 the name of content type
if(entry.slug !== "blog") {
const page = {
path: `/${entry.node.full_slug}`,
component: blogPostTemplate,
context: {
story: entry.node
}
}
createPage(page)
}
})
})
)
})
}
To focus on blog post page, I only included blog post page generation code.
Personally, instead of just copy and paste the above, take a look at whether you succeeded to fetch data or not in GraphiQL from Gatsby.
Just a quick note.
If you copy and paste the data path from gatsby-node.js
source code from above, it only returns an empty array.
It's just that the architecture to write in JS CLI and GraphiQL is different.
Make sure to run yarn develop
again.
Step 4: Create a blog entry template
By default, Gatsby already provides us pages/index.js
in their starter.
This file is a template for non-blog post pages, like Home, About etc...
For the blog post page, we'll use this trick with a bit of arrangement.
Create templates/blog-entry.js
file.
If you're smart, you already recognized that we already imported this file in gatsby-node.js
file.
That's the trick we'll be using 😎
Write your code something like this.
import React from 'react'
import Layout from '../components/Layout'
import Seo from '../components/seo'
import useStoryblok from '../lib/storyblok'
export default function BlogEntry({ pageContext, location }) {
let story = pageContext.story
story = useStoryblok(story, location)
return (
<Layout>
<Seo title={`Blog | ${ story.content.title }`} />
<div>
<div>
<h1>{ story.content.title }</h1>
</div>
<img
src={`https://${ story.content.image }`}
alt={ story.content.image }
/>
</div>
</Layout>
)
}
This time, we'll test out to see the blog post title and an image.
How did I know the path to fetch data?
It's all in a draft JSON from Storyblok ✨
Go to the header menu -> down arrow -> "draft JSON".
It'll open a new browser page with a draft JSON with all the data path you need.
Done!✨
You'll see your very first blog post with a title and an image👏
If you see a 404 page from Gatsby, take a closer look.
You'll find a new page we just created on the page lists.
Click that, and you'll see a result like above.
We managed to route, so the URL of our very first blog post is following from what we named!
As long as we were able to get data for this blog post title and image, we're good to go to fetch rich text data.
In this case, our blog main contents.
Step 5: Fetch rich text data
In order to do so, we need 1 thing to prepare.
Remember we installed storyblok-rich-text-renderer
?
Now is the time to use this gem 💎
Import storyblok-rich-text-renderer
in your templates/blog-entry.js
file.
Also, use render
to render a rich text data.
import React from 'react'
import Layout from '../components/Layout'
import Seo from '../components/seo'
import useStoryblok from '../lib/storyblok'
// 👇 Import `storyblok-rich-text-renderer`
import { render } from 'storyblok-rich-text-react-renderer'
export default function BlogEntry({ pageContext, location }) {
let story = pageContext.story
story = useStoryblok(story, location)
return (
<Layout>
<Seo title={`Blog | ${ story.content.title }`} />
<div>
<div>
<p>{ story.content.category }</p>
<h1>
{ story.content.title }
</h1>
<p>{ story.content.intro }</p>
</div>
<img
src={`https://${ story.content.image }`}
alt={ story.content.image }
/>
</div>
<div>
{/* render a rich text data */}
{ render(story.content.long_text) }
</div>
</Layout>
)
}
Done!
We see our rich text data is displaying!
(🗒 I added category tag and intro. You can add contents as you wish like this.)
Hope this blog post helps with what you were looking for!
Top comments (0)