Need a blog? Use GitHub as your CMS.

Alex White
6 min readJun 5, 2020

Why install Wordpress, Drupal or Ghost when you can use the markdown editor and pull request functionality of GitHub as the backend for your next blog?

In this article, we’ll build a simple blog using GitHub, Nuxt (Vue.js), Nuxt Content and Zeit Vercel.

  1. We’ll start off by scaffolding a Nuxt project. Open a terminal and run:
npx create-nuxt-app myblog

2. Answer the prompts following this screenshot:

Choose JavaScript with Yarn, Tailwind CSS and Single Page App. Leave the rest to ‘none’

3. Next, run the following commands to install Nuxt Content and start your Nuxt site:

cd myblog
yarn add @nuxt/content
yarn dev

4. To get started with the Nuxt Content plugin, open up nuxt.config.js and change the modules section to this:

modules: [
'@nuxt/content'
],

Nuxt Content allows us to use a GraphQL like query structure to fetch and display static files. In this case, we’ll be using it to display .md page for our blog.

5. Still in the nuxt.config.js file, add the following section to the file

generate: {
async routes () {
const { $content } = require('@nuxt/content')
const files = await $content().only(['path']).fetch()

return files.map(file => file.path === '/index' ? '/' : file.path)
}

This allows us to create static routes for dynamic parameters, which is necessary when later deploying to Vercel.

6. Let’s start our blog by creating a page listing each article. Under the pages folder, open up index.vue and change the file to the following code:

<template><main class="container mx-auto py-12"><ul><li v-for="{ title, slug, date } in articles" class="pb-6" :key="slug"><nuxt-link :to="`/articles/${slug}`"><span class="block text-lg font-bold">{{ title }}</span><span class="block text-sm font-base text-grey-700">{{ date }}</span></nuxt-link></li></ul></main></template><script>export default {async asyncData({ $content }) {const articles = await $content("articles").only(["title", "slug", "date"]).sortBy("date").fetch();return { articles };}};</script>

Let’s walk through this code a bit. In the script section, we are using $content provided by Nuxt Content to query for our articles. We do this in asyncData , which happens before component initialization.

We use the only method to specify which parts of the articles we want, and finally we sort by the date field.

In the template section, we simply iterate through each article, displaying the title and date. We create a link to the article using the slug property.

7. If you try visiting the site with localhost:3000 , you’ll get the following error

“Not Found, Back to the home page” error message.

This is because we haven’t yet added any articles.

8. Create a markdown file called my-first-article.md in the following directory myblog/content/articles/my-first-article.md .

VSCode showing the markdown file in `content/articles/my-first-article.md`

Nuxt Content uses the content directory to search for files.

9. Paste the following into your new markdown file:

---title: My First Postdate: 2020-06-01---# My first articleHello, world!

At the top of this markdown file we define a couple of fields, the title and the date . If you remember, we specifically select these in our query in the index.vue file.

10. Restart yarn dev and visit localhost:3000 again, this time you should see your article on the page!

localhost:3000 showing the title and date of our article

The final step on the Vue side is to add a page that will display the content of the article.

11. Create a new file named myblog/pages/articles/_slug.vue

Nuxt uses the underscore notation to define pages for parameters. So localhost:3000/articles/my-first-article will route to our _slug.vue file, and expose my-first-article as a parameter.

12. Paste the following into _slug.vue

<template><main class="container mx-auto py-12"><nuxt-link to="/" class="text-sm font-bold text-blue-700 pb-6 block">Go back</nuxt-link><h1 class="text-xl font-bold pb-2">{{ article.title }}</h1><nuxt-content :document="article" /></main></template><script>export default {async asyncData({ $content, params }) {const article = await $content(`articles/${params.slug}`).fetch();return { article };}};</script>

Again in asyncData we are loading article content using Nuxt Content. This time, we use the slug parameter provided to us by Nuxt to specify the exact article we wish to load.

In our template section, we display the article title, and use the nuxt-content component to easily render the body of the article’s markdown file.

13. Back in your browser, click on the article and you should now be able to see the content of it!

localhost:3000/articles/my-first-article displaying the contents of our markdown file

That’s all for the Vue/Nuxt side of things, next up we need to get this site on the web!

14. Create an empty repository on GitHub and push your files to it. If it’s your first time using GitHub, follow these instructions.

GitHub page showing the Nuxt site code

15. Now that we have our code on GitHub, we’ll use Zeit Vercel to deploy on the internet. Create a Vercel account, and visit https://vercel.com/import/git#import-github to import your blog’s repository.

Vercel repository import screen

Leave the root directory as ./ and use the following settings to setup the build process.

Set build command to `nuxt generate`, output directory to `dist` and development command to `nuxt`

16. Vercel will now build and deploy your website! Click the link it provides you after the deployment and you should see your article.

Article list page showing our markdown article after Vercel deploy.

Now for the fun part, we’ll use GitHub’s PR process to create, preview and deploy a new article!

17. In GitHub, navigate to the content/articles folder and click Create new file

The articles folder on GitHub

18. Enter my-second-article.md for the title, and paste the following into the body

---
title: My Second Post
date: 2020-06-02
---
# My Second articleIsn't this really cool!

19. Click the Preview tab to see a preview of the markdown you entered.

The preview tab on Github showing our article’s rendered markdown

20. Select Create a new branch for this commit and start a pull request , then enter a name for the pull request (see above screenshot).

21. On the next screen, click Create pull request

GitHub’s “Open a pull request” page

22. After a minute or so, Vercel will add a deployment preview to your pull request. You can use this to preview your new article before adding it to your site (this would be especially useful once you set your Vercel project up with a domain name).

GitHub showing a “View deployment” preview link on the pull request

23. Once you click “View deployment”, you should see both articles on the homepage 🎉

Our blog showing both articles on the homepage

24. Finally, go ahead and click “Merge pull request”. The article will be added to the blog, which will cause Vercel to kick off a new deployment. After a minute or so, the article should show up with the main URL associated with your Vercel. Check it out!

Using this setup, you can utilize GitHub to write and preview articles, and have them automatically deployed to your blog by Vercel! Some good next steps would be to improve the look and feel of the site, and add a custom domain name!

--

--