Enter the world of static site generation and the JAMstack using Gridsome. Learn to build a blog using Markdown and GraphQL, and then deploy it to Netlify.
The web is ever evolving and the need to stay updated as developers is really important. In this article, I’ll be introducing you to the world of static site generation and the JAMstack using Gridsome. At the end of the article we’ll build a blog using Markdown as the generated content and GraphQL to query posts that will be displayed on the pages, and then we’ll see how to deploy it to Netlify.
Static Site Generators are part of a new hybrid approach to web development that allows you to build a powerful website locally on your computer but pre-builds the site into static files for deployment. JAMstack is a new way of building websites and applications that delivers better performance, higher security, lower cost of scaling and better developer experience.
Table of Contents:
Gridsome is a Vue.js-powered static site generator for creating fast and secure websites that can be deployed anywhere. It makes it easy for developers to build modern JAMstack websites.
Gridsome comes bundled with some features that are hard to miss, and this makes it one of the most sought-after static site generators out there. Some of these features include:
In order to follow through with this tutorial, You should have a basic knowledge of the following:
We’ll need to set up a new Gridsome project, and to do so we’ll be required to run the following commands.
For the first step, install the Gridsome CLI on your computer using npm or yarn.
$ npm install --global @gridsome/cli or
$ yarn global add @gridsome/cli
The next step after installing the CLI is to go ahead and create a new project called Telerik-blog
and run the project.
// create a new gridsome project
$ gridsome create telerik-blog
$ cd telerik-blog
$ gridsome develop
After running these commands, your local dev server should be running at http://localhost:8080
with the sample page displayed below.
If we try to change anything on this layout page then we’ll see that it automatically changes what we have on the screen. This is as a result of Gridsome Hot Reloading feature we talked about earlier.
We’ll get started by describing what we are trying to achieve with the blog — we’ll have a single page with a list of posts and have each post with content in Markdown. In order to achieve this, we’ll need to install a Gridsome Plugin called gridsome/source-filesystem
that helps transform files into content that can be fetched with GraphQL in your components. Go ahead and install the package using this command:
yarn add @gridsome/source-filesystem or
npm install @gridsome/source-filesystem
and configure it within the gridsome.config.js
file:
module.exports = {
siteName: 'Gridsome Blog',
siteDescription: 'A simple blog designed with Gridsome',
plugins: [
{
use: '@gridsome/source-filesystem',
options: {
path: 'content/posts/**/*.md',
typeName: 'Post',
route: '/blog/:slug'
}
}
]
}
The configuration above is what we need to set up the source-filesystem
plugin. The options set here:
.vue
file in src/templates
must match the typeName
to have a template for it.localhost:8080/blog/new-post
Now that we have that set up, we can create a content/posts folder. This is where all markdown content for our blog will be stored. We also want to include syntax highlight to our blog.
The @gridsome/remark-prismjs plugin adds that to code blocks. We can set it within the gridsome.config.js:
yarn add @gridsome/remark-prismjs or
npm install @gridsome/remark-prismjs
Then go ahead to main.js and import prismjs CSS Theme.
import 'prismjs/themes/prism.css'
export default function (Vue) {
// ...
}
In gridsome.config.js, add syntax highlighter to all markdown sources:
transformers: {
//Add markdown support to all file-system sources
remark: {
externalLinksTarget: '_blank',
externalLinksRel: ['nofollow', 'noopener', 'noreferrer'],
plugins: [
'@gridsome/remark-prismjs'
]
}
},
Gridsome uses Layouts as a wrapper for pages and templates. Layouts contain components like header, footer or sidebars, etc. and a slot
component where content coming from pages and templates is inserted.
<template>
<div class="layout">
<slot/> <!-- Page/Template will be inserted here -->
<div class="footer">
<p>
Built with
<a class="link" href="//gridsome.org">Gridsome</a>
& Made with ❤️ by
<a class="link" href="//twitter.com/lauragift21">Gift Egwuenu</a>
</p>
</div>
</div>
</template>
The above code block is our Default.vue component. The styling for the blog is populated in the style tag. We can find more details about the styling used in the GitHub Repo.
<style>
body {
font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Roboto,
"Helvetica Neue", Arial, sans-serif;
margin: 0;
padding: 0;
line-height: 1.5;
border: 15px solid #fecd43;
min-height: 100vh;
}
.layout {
max-width: 760px;
margin: 0 auto;
padding-left: 20px;
padding-right: 20px;
}
.footer {
padding-top: calc(30em / 4);
text-align: center;
font-size: 1em;
}
.link {
border: 2px dashed #fecd43;
padding: 7px;
color: #333;
text-decoration: none;
}
</style>
The Page layout will be where all the blog posts are listed and also will serve as the homepage. In Gridsome, Pages are used for normal pages and for listing & paginate GraphQL collections. In this case our blog posts is the collection. The page URL is generated based on the location and name of the file. As an example, if we create a file within the pages directory and name it Index.vue
, it will be treated as index.html
, which is the home page. The same applies if we create a file and call it About.vue
— it’ll be treated as about.html
and will be linked as /about
. That is how routing works in Pages. Because we only want to display all posts
in a single page, we can go ahead and create Index.vue
file, or if we have one generated for us already then we can use that.
Our Index.vue
should look like this:
<template>
<Layout>
<header class="header">
<h1>Gridsome Blog</h1>
<p>A simple blog designed with Gridsome</p>
</header>
</Layout>
</template>
And with that, we should have this page when we navigate to the homepage.
Now that we have the homepage, we can go ahead and create a list of blog posts and display that on the page. We can create a PostList.vue
file within the components directory, in which we’ll create the layout for displaying a list of post for our blog.
<template>
<div class="post-list">
<hr class="line" />
<p class="date" v-html="post.date" />
<h1 class="title" v-html="post.title" />
<p class="description" v-html="post.description" />
<b> {{post.timeToRead}} min read </b>  
<g-link :to="post.path" class="read">Read More...</g-link>
</div>
</template>
<script>
export default {
props: ["post"],
};
</script>
Within this file, we have content for displaying a list of posts and we are also adding a post
props that enable us to pass data from the parent component down to the PostList
child component.
Head back to the Index.vue
within the Pages directory. Remember I previously mentioned Gridsome has a centralized data management for all your data, which in our case is GraphQL
. It uses <page-query>
and <static-query>
to fetch data into pages, template and components. Here we need to pull all posts we have in our content directory written in Markdown and display them within our Vue component.
<page-query>
query {
allPost {
totalCount
edges {
node {
id
title
timeToRead
description
date (format: "D MMMM YYYY")
path
}
}
}
}
</page-query>
Now, we have the content in the Vue component we can pass them to the PostList.vue
component like this:
<section class="posts">
<PostList v-for="edge in $page.allPost.edges" :key="edge.node.id" :post="edge.node" />
</section>
Now we have a list of posts from the content
folder displayed. The next step is to display a single post when one of these posts is clicked. We’ll be using a template to handle this. In Gridsome, a Template is used for displaying a single post view to GraphQL collections. Add a Post.vue
file within the templates directory with the following content.
<template>
<Layout>
<br>
<g-link to="/" class="link"> ← Go Back</g-link>
<div class="post-title">
<h1>{{$page.post.title}}</h1>
<p class="post-date"> {{ $page.post.date}} | {{$page.post.timeToRead}} min read
</p>
</div>
<div class="post-content">
<p v-html="$page.post.content" />
</div>
</Layout>
</template>
And to query the content of a single post, we’ll be using a page-query
with the following:
<page-query>
query Post ($path: String!) {
post: post (path: $path) {
id
title
content
date (format: "D MMMM YYYY")
timeToRead
}
}
</page-query>
With that done, when you click on read more
on the homepage, you should see the content of a single post displayed with a slug
using the post title like we configured in gridsome.config.js
.
Our blog is complete! The next step is to deploy, and for this we’ll be using Netlify. Head over to Netlify website and create a new site. Make sure you have your codebase on GitHub. You can find the Repo for this project on GitHub. The next step is to add the following configuration.
After creating a new site on Netlify we’ll be prompted with a modal to configure our site. Go ahead and setup the branch to deploy as master
and the build configurations should be gridsome build
as the command and dist
as the publish directory. After we’ve done that we can then click on deploy site and we’ll have our site deployed with a URL to visit in no time. The URL for this project can be found here.
In this article, we have demonstrated how to build a blog in Vue.js using Gridsome and Markdown. You can see it can be pretty straightforward to implement and in no time you have a personal blog running. Feel free to check out the GitHub Repo and Gridsome Documentation to learn more.
Want to learn more about creating great web apps? It all starts out with Kendo UI - the complete UI component library that allows you to quickly build high-quality, responsive apps. It includes everything you need, from grids and charts to dropdowns and gauges.
Gift Egwuenu is a developer advocate and technical educator with more than five years of experience in the web development industry. She has a passion for building tools and products that help businesses grow. She enjoys sharing her knowledge and experience through speaking engagements, writing and other educational initiatives. Gift's areas of expertise include web development, JAMstack and career advancement, and she is dedicated to helping others improve their skills and succeed in the tech industry. Gift enjoys reading, cooking and traveling when she is not working.