Photo by Catherine Heath on Unsplash
This is part two of a series on building a file-based blog from scratch with Gridsome. Find the full series here.
In the last part, we started with a basic static site built with Gridsome.
Now, we will write Markdown files, load them into Gridsome with a source
-plugin, and display them as blog posts using template components.
Gridsome offers a plugin system. With it you can e.g. add an RSS feed to your site, add search, add analytics, or load data from a CMS of your choice.
Take a look at the plugins list to discover what's possible!
When you want to add data to your Gridsome project, you need to add a source plugin.
To load files from the local filesystem, we'll add the source-filesystem
plugin:
yarn add @gridsome/source-filesystem
Add plugin to gridsome.config.js
module.exports = {
siteName: 'Gridsome',
plugins: [
{
use: '@gridsome/source-filesystem',
options: {
typeName: 'BlogPost',
path: './content/blog/**/*.md',
}
}
],
templates: {
BlogPost: '/blog/:year/:month/:day/:slug'
}
}
To parse markdown files, we need to add the remark plugin:
yarn add @gridsome/transformer-remark
We don't need to configure anything, Gridsome uses it automatically.
First, add the folder where Gridsome looks for blog posts: mkdir -p content/blog
.
Now, let's create a blog post.
Create a file under content/blog/2020-06-05-first-post.md
with the following content:
---
slug: "first-post"
date: "2020-06-05"
title: "Hipster Ipsum"
---
I'm baby chartreuse knausgaard gastropub deep v mlkshk pickled crucifix chicharrones meggings. Listicle jianbing tbh sriracha tofu, waistcoat post-ironic copper mug williamsburg scenester. Banh mi tilde swag beard. PBR&B disrupt affogato 8-bit fanny pack. Tacos fam brooklyn jean shorts. Taiyaki fam +1 tote bag chia palo santo.
Banh mi authentic fashion axe affogato shoreditch umami bicycle rights keytar put a bird on it drinking vinegar pitchfork taxidermy. Synth pinterest bespoke, taiyaki williamsburg chambray cloud bread readymade. Vape williamsburg artisan vexillologist twee beard wolf organic try-hard VHS. Artisan polaroid jianbing semiotics retro mumblecore. Hexagon YOLO gastropub sriracha DIY next level.
Ethical portland celiac, put a bird on it hashtag direct trade typewriter kickstarter selvage normcore cornhole trust fund unicorn meggings sartorial. Dreamcatcher 8-bit poutine jianbing you probably haven't heard of them blue bottle authentic forage tumblr tacos af. Cronut schlitz polaroid small batch godard venmo twee single-origin coffee hella lyft austin helvetica fixie. Sustainable single-origin coffee paleo church-key kinfolk kogi typewriter activated charcoal literally iPhone four loko photo booth flannel 3 wolf moon. Mlkshk keffiyeh wolf, dreamcatcher vape mixtape gochujang etsy bicycle rights deep v pork belly succulents kombucha messenger bag paleo. Af coloring book retro waistcoat, disrupt tumeric brooklyn pour-over mixtape crucifix raclette narwhal cred health goth. Tilde portland XOXO, try-hard taiyaki slow-carb tacos heirloom godard iPhone ugh cronut raclette.
Selvage twee viral, lyft chartreuse swag crucifix hexagon lo-fi meggings literally. Jianbing knausgaard vexillologist, sustainable yr twee tote bag cray keytar schlitz slow-carb DIY dreamcatcher brooklyn listicle. Chambray letterpress flexitarian meditation gentrify. Single-origin coffee lyft iPhone street art, hot chicken yr live-edge gentrify waistcoat.
Dummy text? More like dummy thicc text, amirite?
The first 5 lines are called "front matter". It contains the metadata for your posts. This post contains a slug (human readable part of URL), the publishing date, and the title.
After that, we write our post in regular Markdown syntax.
Now let us add the BlogPost.vue
template under src/templates
:
<template>
<Layout>
<h1>{{ $page.post.title }}</h1>
<span>{{ $page.post.date }}</span>
<div v-html="$page.post.content" />
</Layout>
</template>
<page-query>
query Post ($path: String!) {
post: blogPost (path: $path) {
title
date (format: "MMMM D, Y")
content
}
}
</page-query>
<script>
export default {
metaInfo () {
return {
title: this.$page.post.title
}
},
}
</script>
You can see that the page-query
this time loads all blog posts with the blogPost(path)
query.
This works because the current path in Gridsome is always available as $path
.
In the script
section, we define the page's <title>
meta tag as the blog post title.
The template
section defines our HTML.
We can access the results of the post query as $page.post
.
There we have the title
, date
, and content
available, because we request these properties in the blogPost
page-query
.
In our template, we use these three properties.
First the title as a h1
heading, then the post date.
Finally, we load the post's content into a div
.
v-html
is Vue's property to directly inject HTML into a DOM node.
This property is unsafe, because it does not validate the HTML, which can lead to XSS vulnerabilities.
We can use it in this case, because we generate the Blog post HTML from Markdown files we write ourselves.
Let's start up our blog with gridsome develop
.
We get can go to our /pages
overview site and voilà, our blog post appears!
When we click on the link, we see our blog post:
That’s it for this post on loading Markdown files with Gridsome. In the next part of this series, we will add styling to this blog with Tailwind CSS. We'll also improve UX by adding a blog posts overview page!