My personal website has gone through a few blogging services such as WardrobeCMS, OctoberCMS and WordPress, but after having some issues created by some updates, I decided to move away. This is when I decided to use a static site generator and found VuePress.

VuePress is built on VueJS and will convert markdown files to HTML web pages. It's small, fast and much more secure than WordPress or any website containing backend code. Another benefit is cost because it doesn't cost anything to host a static website using GitHub Pages, Netlify or GitLab Pages.

Before you begin, please ensure you have Node installed and working on your machine.

Setting up VuePress

First we need to install VuePress using Node and create our first webpage using Markdown which will be our index page. Please be sure to create a project directory and run the following with your chosen terminal inside of your project directory.

npm install -g vuepress
echo '# Hello VuePress' > README>md

Now we can transform our markdown file into a working webpage by running.

vuepress dev

You can now view your VuePress website at localhost:8080. This is the most simple version of your website, but now it's time to take it one step further.

Further Configuration

Next we want to make a config.js file in /docs/.vuepress/config.js and add the following.

module.exports = {
    title: "Website title",
    description: "Website description",
    dest: 'pages',
};

The dest path tells VuePress where you want your project to be built and I personally place it in the /pages directory. You build your project when you want your website to go live which you can see if you run.

vuepress build

If you do run this command on your dev environment then I recommend that you delete that directory and make sure you don't commit it into your git repo.

We should also move our README.md file into the docs directory which is where most of our website files will live from.

NPM Packages

In order to manage our packages we should create a package.json in the root of our project directory. You can place the following code inside.

{
  "name": "michaelbrooks",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "docs:dev": "vuepress dev docs",
    "docs:build": "vuepress build docs"
  },
  "dependencies": {
    "moment": "^2.24.0",
    "vuepress": "^1.0.3",
    "yaml-front-matter": "^4.0.0"
  }
}

The name, version and description can be changed to your use-case or you could remove it depending on your personal preference. The main points to look at are "scripts" and "dependencies". The dependencies are what we need in order to get our project running on our server and we include "vuepress" because it won't be installed globally on our production server.

The scripts can be used via npm commands and are run after all packages in your project are installed e.g.

npm run docs:dev and npm run docs:build

Let's install our packges now by running npm install and once the packages have finished installing, we can run npm run docs:dev.

We now have a minimal setup which is great if you want a simple static website, but we need to take this one step further so we have a blog.

Let's get our blog website rolling

For the directory structure I chose to place all my markdown files at the root of the docs directory, but if you want to have a /blog separator in your URL, then go ahead and create that directory now. You can then place any blog posts in there as markdown.

Let's create our blog's landing page. I created a blog.md file inside the docs repository and added the following.

---
title: Example blog
description: This is my example blog
---

# Blog

The text between --- is known as frontmatter, here you can add page titles, description, images and much more.

Let's also create an example blog post blog post.

---
title: Example blog post
date: 2019-06-26
type: post
---

# Example blog post

This is our first example blog post.

Custom Vue Components

In order to display our blog posts in our blog.md page, we first need to create a Vue component. In /doc/.vuepress/components/BlogIndex.vue you can added the following inside your template.

<template>
    <div>
        <!-- Loop through all posts. -->
        <div v-for="post in posts">
            <!-- Create a link to the post's url. This can also be removed if you don't plan to have any images. -->
            <router-link :to="post.path">
                <!-- If a post has the frontmatter "coverImage" then display that image. -->
                <div v-if="typeof post.frontmatter.coverImage !== 'undefined'" >
                    <img :src="post.frontmatter.coverImage" alt="" />
                </div>
            </router-link>
            <!-- End optional block which can be deleted. -->
            <!-- Display the post's frontmatter title -->
            <h3><router-link :to="post.path">{{ post.frontmatter.title }}</router-link></h3>
            <!-- Display the post's frontmatter date. -->
            <p>Posted On: {{ formateDate(post.frontmatter.date) }}</p>
            <!-- Display the post's frontmatter description. -->
            <p>{{ post.frontmatter.description. }}</p>
            <!-- Add read more with a link. -->
            <p><router-link :to="post.path">Read More >>></router-link></p>
        </div>
        <a rel="alternate" type="application/rss+xml" href="/rss.xml">RSS</a>
    </div>
</template>

Next we need to add the script tags which will control what's displayed inside of the template tags.

<script>
    // Import moment into our file
    import moment from "moment"
    export default {
        props: [
            // This will limit the amount of blog posts shown
            'limit',
        ],
        methods: {
            // Control how our data is formatted. You can change to format accoring to JS date format.
            formateDate(date, format = 'MMM D, YY') {
                return moment(date).format(format)
            }
        },
        computed: {
            // Build a list of all our posts ready to be displayed.
            posts() {
                let posts = this.$site.pages
                    .filter(post => !post.frontmatter.blog_index)
                    .filter(post => !post.path.startsWith('/archived/'))
                    .sort((a, b) => new Date(b.frontmatter.date) - new Date(a.frontmatter.date));
                if (this.limit > 0) {
                    posts = posts.slice(0, this.limit);
                }
                return posts;
            }
        }
    }
</script>

Now we have our BlogIndex.vue file created, we can now reference this inside of our blog.md file which will look like this.

---
title: Example blog
description: This is my example blog
---

# Blog

<BlogIndex category="current" limit="20" />

You place the BlogIndex tag into any file where you'd like to display a list of posts. I have it inside my README displaying the latest post and my blog.md file displaying 20 posts. You can see my personal website's code here if you're curious to see more.

I hope you enjoyed this blog post, and be sure to sign up and learn how to deploy with Netlify. As well as learning how you can use NetlifyCMS in order to manage your blog posts from an admin panel.