This tutorial assumes you have some familiarity with Vue.
Gridsome Is a very fast Jamstack framework made with Vue. It allows for great SEO, has a GraphQL data layer, a robust plugin ecosystem and is easy to connect to a CMS.
Check your node version and make sure you have the correct version installed. It's recommended to use 14+ I'm using 16.3 for this tutorial. You can check your node version by typing node -v
in your terminal.
When installing, use Yarn or NPM, don't mix and match the two.
We'll first need to install the Gridsome CLI globally. This will allow us to use gridsome create
for our new project.
npm install --global @gridsome/clioryarn global add @gridsome/cli
You can choose whatever name you want for the project. I'll name mine gridsome-blog
. After creating your project go into the folder and then run the project.
gridsome create gridsome-blogcd gridsome-bloggridsome develop
You should see your new project on http://localhost:8080
Now that the boilerplate layout is set up by gridsome create, let's install some packages specific to creating a blog.
// transforms content for graphqlyarn add @gridsome/source-filesystemornpm install @gridsome/source-filesystem// Syntax highlighter for markdown code blocksyarn add @gridsome/remark-prismjsornpm install @gridsome/remark-prismjs// markdown transformeryarn add @gridsome/transformer-remarkornpm install @gridsome/transformer-remark
Now let's set up the packages we just installed. Open up your gridsome.config.js
file and add the below code.
module.exports = { plugins: [ { use: '@gridsome/source-filesystem', options: { typeName: 'Post', path: './content/blog/**/*.md', }, }, ], transformers: { remark: { externalLinksTarget: '_blank', externalLinksRel: ['nofollow', 'noopener', 'noreferrer'], plugins: ['@gridsome/remark-prismjs'], }, }, templates: { Post: '/:title', },};
./content/blog/**/*.md
which we have not made yet.http://localhost:8080/blog-post-two/
For styling, I'm going to be using scss and Bulma. To match the card styles in this tutorial you'll need to set up Bulma and create an src/assets/style/index.scss
file path.
Install Bulma, sass and sass-loader. Gridsome 0.7.0 is still on Webpack 4 which requires a lower sass-loader version.
yarn add -D sass-loader@^10.1.1 sass
yarn add bulma
In our newly created index.scss
file, import bulma.
@import "~bulma";
In our main.js
file, import our newly created index.scss file to load bulma and any additional partial scss stylesheets you might create
import '~/assets/style/index.scss';
Now we're ready to create our blog list and blog pages that will show the text in the .md files we created earlier.
To get the path we need for Gridsome to read our markdown files, create a content and blog folder starting in the root file ./content/blog/
. I'm going to create two markdown files first-blog.md
and second-blog.md
. These will be our two blog posts.
Add some fake data to your blog post using an Ipsum. I use Lorem Ipsum and Cat Ipsum in mine.
Here's an example of the blog structure in the .md file. I got some images from unsplash for my blog posts.
---title: Blog post twodate: 2022-09-22published: trueseries: falsecover_image: ../images/mountains.jpgcanonical_url: falsealt: mountainsdescription: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit.'---Cat ipsum dolor sit amet
All of our individual blog posts that contain the data in our markdown files will have the same template layout. Under the templates folder create a file called Post.vue
Add the code below to Post.vue to create the HTML layout with Bulma styles and query to get the data from our markdown files we created earlier. The page will have a title, an image, and the content of the blog.
After adding this code you should be able to go to /blog-post-one/
and see the image and content of your blog post
<template> <Layout> <div class="has-text-centered"> <h1 class="title is-1"> {{ $page.post.title }} </h1> </div> <div class="post content section container"> <figure v-if="$page.post.cover_image" class="image is-16by9"> <g-image :alt="$page.post.alt" :src="$page.post.cover_image" /> </figure> <div v-html="$page.post.content" /> </div> </Layout></template><script>export default { metaInfo() { return { title: this.$page.post.title, meta: [ { name: 'description', content: this.$page.post.description, }, ], }; },};</script><page-query>query Post($id: ID!) { post: post(id: $id) { title path description alt content cover_image(width: 860, blur: 10) }}</page-query>
Now that we have our markdown files and blog page created, let's create a blog post card list that will allow us to show all the blogs at once.
In our components folder create a file named PostList.vue
. Here, we're going to create the card style that will show up for each individual blog post on our landing page.
<template> <div class="card"> <!-- if there is an image show it. If user clicks image take to url path --> <g-link v-if="post.cover_image" class="card-image" :to="post.path"> <figure class="image is-16by9"> <g-image :alt="post.alt" :src="post.cover_image" fit="contain" /> </figure> </g-link> <div class="card-content has-text-centered"> <!-- click the title link to go to blog post --> <g-link :to="post.path" class=" has-text-weight-bold is-size-3"> {{ post.title }} </g-link> <!-- show description section of blog --> <div class="content" v-html="post.description" /> </div> </div></template><script>export default { props: { post: { type: Object, default() { return {}; }, }, },};</script><style lang="scss">.card { width: 500px; height: max-content; margin-top: 30px;}</style>
Under our pages folder in the index.vue file, let's loop through or PostList card component to show all the blog posts we have.
<template> <Layout> <header class="header"> <h1 class="title size-1 has-text-centered pt-5">Gridsome Blog Tutorial</h1> </header> <main> <div class="container"> <!-- loop through blog card component to show blogs --> <PostList v-for="edge in $page.posts.edges" :key="edge.node.id" :post="edge.node" /> </div> </main> </Layout></template><page-query> query { posts: allPost(filter: { published: { eq: true } }) { edges { node { id title description alt cover_image( blur: 10) path } } } } </page-query><script>import PostList from '~/components/PostList.vue';export default { components: { PostList, }, metaInfo: { title: 'Gridsome Blog Tutorial', },};</script><style>.container { display: grid; justify-content: center;}main { margin: 4% 0;}</style>
Now you should be able to see your blog cards on the landing page and click the title link to go see the indvidual blog page.
You can get the code for the tutorial on my Github page. If you found this tutorial helpful please star it on github!