This is part eighteen of a series on building a file-based blog from scratch with Gridsome. Find the full series here.
Have you ever wondered how you can get dynamic content inside your blog posts?
Stuff like CodePens, image carousels, or quizzes?
That's totally possible in Gridsome with markdown posts.
vue-remark
to the rescue!
At the end of this article, you will know how to add dynamic Vue components to your blog posts. We will build a spoiler section that you can show and hide by clicking a button.
First, install the package: yarn add @gridsome/vue-remark
.
Then, we will replace the current @gridsome/source-filesystem
with @gridsome/vue-remark
in gridsome.config.js
:
// ... File contents...
module.exports = {
siteName: 'Awesome Blog',
siteDescription: 'Blog about awesome lists, collections of resources around a specific technology.',
siteUrl: process.env.DEPLOY_URL || 'https://blog.awesome',
metadata: {
author: 'Simon Menssen',
twitter: {
site: '@simonmenssen',
creator: '@simonmenssen'
}
},
plugins: [
// add the following config for @gridsome/vue-remark
{
use: '@gridsome/vue-remark',
options: {
typeName: 'BlogPost',
baseDir: './content/blog',
route: '/:slug',
template: './src/templates/BlogPost.vue',
plugins: [
['gridsome-plugin-remark-shiki', { theme: 'nord', skipInline: true }]
],
refs: {
tags: {
typeName: 'Tag',
create: true
}
}
}
},
{
use: '@gridsome/plugin-sitemap',
options: {
exclude: ['/privacy', '/legal']
}
}
],
templates: {
// remove the BlogPost template here
Tag: '/tag/:id'
},
css: {
loaderOptions: {
postcss: {
plugins: postcssPlugins
}
}
}
}
Then we need to edit the BlogPost.vue
component:
<template>
<Layout>
<h1 class="mb-2 text-2xl font-semibold text-strong">
{{ $page.post.title }}
</h1>
<p class="mb-4 font-light text-gray-700">
{{ $page.post.date }}
</p>
<div class="flex flex-wrap mb-4 text-sm">
<g-link
v-for="tag in $page.post.tags"
:key="tag.id"
:to="tag.path"
class="px-2 py-1 mb-4 mr-4 rounded-full bg-softer text-strong hover:text-default hover:bg-soft"
>
{{ tag.title }}
</g-link>
</div>
<!-- This is the figure element we added: -->
<figure
v-if="$page.post.image"
class="flex flex-col"
>
<g-image
:alt="$page.post.image.alt"
:src="$page.post.image.path"
class="mb-2"
/>
<figcaption
class="self-center mb-10 image-caption"
v-html="$page.post.image.caption"
/>
</figure>
<!-- change the following div -->
<div
class="mb-16 markdown"
>
<VueRemarkContent />
</div>
</Layout>
</template>
<page-query>
query Post ($id: ID!) {
post: blogPost(id: $id) {
title
date (format: "MMMM D, Y")
summary
path
tags {
id
path
title
}
image {
alt
path
caption
}
}
}
</page-query>
When we now start the blog with yarn develop
, our blog renders like before.
Let's create a Vue spoiler-component!
Luckily, Browsers support a native "spoiler component".
Here's the code for src/components/SpoilerSafe.vue
:
<template>
<details class="p-4">
<summary>{{ summary }}</summary>
<slot />
</details>
</template>
<script>
export default {
props: {
summary: {
type: String,
required: true
}
}
}
</script>
We can then use this component inside our blog posts like this:
---
slug: "fourth-post"
date: "2030-07-30"
title: "The Future of Design"
tags: ["future", "design"]
summary: "Synth pinterest bespoke, taiyaki williamsburg chambray cloud bread readymade."
---
import SpoilerSafe from '~/components/SpoilerSafe.vue'
...
<spoiler-safe summary="Reveal spoiler">
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.
</spoiler-safe>
...
Our spoiler component now looks like this:
That’s it for this post on Markdown widgets and how we can use them in our Gridsome blog.
This is also the last planned part for my Gridsome series!
If you have more questions about Gridsome or have another idea for an article, shoot me an email at simon@mannes.tech.