Create YOUR next static blog in Vuepress and Vue 
Tags: tutorial, webdev, javascript, vue
Published: 2019-07-15 17:56:01

---
title: Create YOUR next static blog in Vuepress and Vue 
published: true
description: 
tags: tutorial, webdev, javascript, vue
cover_image: https://thepracticaldev.s3.amazonaws.com/i/8hgg12cy4fkz41n8g8mw.jpg
canonical_url: https://softchris.github.io/pages/vue-vuepress.html
---

Follow me on [Twitter](https://twitter.com/chris_noring), happy to take your suggestions on topics or improvements /Chris

> The idea with this series is to have a look at how you can build your own blog using one of the known static site generators. 

TLDR; Yes this article is a bit long but well worth a read as it manages to tell you how to not only get started with your own homepage but also how to build custom components and use the default theme. Also if you never used a static site generator before, this is VERY easy to get started with.

Building your own blog can be a very ambitious project where you spend time coding or integrating and tweaking different components that you absolutely must have or something dead simple, where you just focus on writing the article.

Blogs are usually static sites and people often don't want to write their blog posts in HTML but prefer to write them in something else like Markdown or just plain text. For that reason, static site generator tools exist that caters to beginners as well as the most advanced user possible.

> I'm definitely one of those people, Markdown FTW and the less I need to deal with my blog the better :)

This is part of a series of articles in which we look at different static site generators. In this article, we will focus on VuePress, a static site generator from the Vue team themselves.

We will cover the following: 

- **Install and Set up**. This part is pretty important that it's smooth and easy 
- **Hello world** Creating that first page is an important part of the experience, let's see how fast we can be up and running.
- **Static pages** for CV, About and other pages
- **Creating blog posts** We look at different static site generators with the intention of being able to use it as a blog engine so we need to understand how we should name those files, how we work with frontmatter, tags, slugs and other things 
- **Customize** the looks, colors, layout etc. We might be happy with a theme we are given but sometimes we want to be able to tweak the looks. Or even better is there a great default theme we could be using *HINT*
- **Create custom controls** like a list-page of articles. It's a quite common thing to want to list all the articles your blog consist or maybe a tag cloud. The point is we either want to use these kinds of articles or be able to create them ourselves if they aren't available.

## Resources
There are some great links you should have a look at if you really want to get into using Vuepress

- [Official Docs](https://vuepress.vuejs.org/)
It contains a lot of info on how to get started, config your site, use themes, work with markdown and so on. 

- [Article on creating a Custom VuePress theme](https://dev.to/vuevixens/build-a-beautiful-website-with-vuepress-and-tailwindcss--3a03)
Excellent article by my colleague [Jen Looper](https://twitter.com/jenlooper) how to create a custom theme.

- [How to create a Custom component](https://www.raymondcamden.com/2018/05/09/adding-a-recent-content-component-to-vuepress)
This excellent article from Raymond really made it click for me how to author a custom component

## Install & Set up
First of all, we need Node.js installed on our system so go and install that first if you don't have it:

> https://nodejs.org/en/download/


To install the Vuepress CLI we will need to do so on a global level, note below how we use the `global` flag for yarn or `-g` for NPM install.

```
yarn global add vuepress # OR npm install -g vuepress
```

**Create a directory**
Next step is to create a directory and place yourself in it:

```
mkdir my-blog
cd my-blog
```

**Create some blog content**

Next step is to create a `README.md` file like so:

```
# My blog

Welcome to my blog
```

**Build and Run our blog**

Next step is to type `vuepress dev` in the terminal:

![](https://thepracticaldev.s3.amazonaws.com/i/m7p0fhsa1imhpshu2jc1.png)

That did a whole slew of things. Adding a theme, applying plugins and ended up serving our page at `http://localhost:8080`

![](https://thepracticaldev.s3.amazonaws.com/i/9gm9pvl5vura8dlnu18n.png)

There we have it. Our first page. 

> THAT WAS FAST.

There is no denying that getting started was ridiculously easy.

However, a good static site generator should be able to do a few tricks so let's move on. 

## Creating static pages

We've already seen how our `README.md` file was turned into our default page but a blog most likely needs a couple of supporting pages like an *about page* or an article list page and so on and a menu would be nice.

### Supporting pages

Let's create some supporting pages `about.md` and `cv.md` so our project now looks like this:

- `README.md`, our default page
- `cv.md`, a page containing our CV
- `about.md`, a page containing more details about us

Our `vuepress` CLI command is already running in the background so when we created the above files with their content, it recompiled and we can now reach these pages at their filename, so `http://localhost:8080/about.html` and also `http://localhost:8080/about`. The latter is rewritten to the HTML version.

![](https://thepracticaldev.s3.amazonaws.com/i/f48sb2i2o1ashrcgvlxo.png)

Just a quick reminder of our file structure so far:

![](https://thepracticaldev.s3.amazonaws.com/i/gw4y3ufqoxrzfwv2f9gf.png)

### Navigation

What about navigation then, how can I navigate between pages? Well lets look at an excerpt we found in the offical docs:

```
[Home](/) <!-- Sends the user to the root README.md -->
[foo](/foo/) <!-- Sends the user to index.html of directory foo -->
[foo heading anchor](/foo/#heading) <!-- Anchors user to a heading in the foo README file -->
[foo - one](/foo/one.html) <!-- You can append .html -->
[foo - two](/foo/two.md) <!-- Or you can append .md -->
```

Ok, that means that we can link to the home page, to a landing page under a directory, to a specific anchor on a page and we can either type the `.md` or `.html` file ending.

> Impressive let's try it out

Change `README.md` to say:

```markdown
# My blog

Welcome to my blog

- [About](/about/)
- [CV](/cv/)
```

lets also add:

```markdown
[Home](/)
```

to the bottom of `about.md` and `cv.md`. Now we have a fully working navigation system between our starting page and our two other pages.

## Make it ready for production
So far we have been using `vuepress dev` to host the blog in the browser, but how do we actually make it ready for production, you know have it generate HTML, CSS and all those other bits? Cause if we look at our file structure right now it's just markdown files. The answer is a simple one, we type:

```
vuepress build
```

Running said command will give you the following result

![](https://thepracticaldev.s3.amazonaws.com/i/9d6y6ctgeqrzhgvy87wp.png)

As indicated this will create a `.vuepress` directory and a `dist` directory under it

![](https://thepracticaldev.s3.amazonaws.com/i/yy4zyd26xdmc78b1mlf0.png)

Above we can see that each of our markdown files has turned into HTML files. We have also gotten a `assets` subdirectory that contains, JavaScript, CSS, and images.

> Almost too easy right?

## Blogging with Markdown

The main reason for us to start evaluating static site generators is finding something that supports our blogging effort. Let's try to list what features we want and things we need to tag each article with:

- **Topic tags**, a way to give the page proper tags. It's important for a reader that they can easily see the content of an article.
- **Title**, a descriptive title is key in having people select to read our article
- **Date**, a date when it was written, it's important that we can assign a date to an article so we easily can see when we wrote it but also group/sort it by datee
- **Code highlight**, this is a must. Reading long lines of source code is unbearable without highlight.

### Write an article
Ok then, lets create a directory `pages` and start creating an article `article.md`. Let's add a few paragraphs and add som code like we are used to, now render it with `vuepress dev`:

![](https://thepracticaldev.s3.amazonaws.com/i/0v3vvvofm10wapff7wbv.png)

Ok, that looks pretty good we got good looking rendering of the article text as some nice highlight of the code. But wait there is more. We can actually indicate specific rows like so:

![](https://thepracticaldev.s3.amazonaws.com/i/otq6i32aec9lcpsj6vnj.png)

> WHAT... 

I know right, so useful when you want to highlight new additions to the code. So how did we do this?

Normally we start a code portion with three `` ` `` backticks and then we add `js` for example to indicate the language, in this case, JavaScript. If we add something to this `{}`, we can indicate rows we want to highlight. To accomplish the above we typed `js{3,4}` after the backticks, to say that we wanted row `3` and `4` highlighted extra.

One more thing about code rendering is that we can enable line numbers by creating a file `config.js` under the directory `.vuepress` and set the `lineNumbers` property like so:

```js
module.exports = {
  markdown: {
    lineNumbers: true
  }
}
```

### Frontmatter
This is the part of the article that goes at the top. We can use this to set things like:

- title
- path
- keywords
- publishing date
- meta information

In Vuepress, we define this header, the *frontmatter* as YAML. It can look like this:

```yaml
---
property: value
objectproperty: 
  prop: value
  prop2: value
---
```

another example is:

```yaml
title: Blogging Like a Hacker
lang: en-US
```

> So when does all of this matter?

First thing you need to know is that the underlying engine to this is Vue and Vue reads in all the different pages as objects and the front matter will be read in as an object.

If we then fill the front matter with interesting information like a title, keywords, publishing data and so on it will be very easy to create different components that can easily showcase your blog info like a list of articles, ordered by date or why not a tag cloud of the most used tags? 

> Ok, yea that sounds neat but how do I do that?

Read on and you will find out in the next section.

## Custom controls
It should be said that there isn't many ready to use controls. However, given how easy it is to create those you don't really need them. Below we will show one simple component, so you get the hang of it and one little more advanced one.

Ok, we just introduced the concept of frontmatter a piece of YAML at the top of each article but how do we actually do something useful with it? The answer is we create custom controls.

> Ok you said that already, but how?

Remember how I said everything is Vue.js? No? Well, it is. This means that if we create a directory `components` under the `.vuepress` directory, that was created when we ran `vue build` we can create Vue components that we can use everywhere on the site. 

> Really? I know how to create Vue components but how do I use them?

Let's start with creating a component `About.vue`

![](https://thepracticaldev.s3.amazonaws.com/i/qzldtrpp1rk0nckkt55b.png)

 and give the file the following content:

```js
// About.vue

<template>
  <div class="box">
    <h2>{{title}}</h2>
    {{message}}<button @click="click">Hi</button>
  </div>
</template>
<script>
export default {
  data() {
    return {
      message: 'about page'
    }
  },
  methods: {
    click() {
      alert('hi')
    }
  },
  props: ['title']
}
</script>
<style scoped>
 .box {
   padding: 20px;
   margin: 2px;
   box-shadow: 0 0 10px black;
 }
</style>
```

The above looks like a quite ordinary Vue.js component that has a data property `message`, an input parameter `title` and a method `click`.

> So you're saying I can use this in page?

Correct, just add it like so in `about.md`:

```
# About

<About title="about me" />
```

> Wait, so you are mixing markdown and HTML elements?

Yup, that just works. The result looks like this:

![](https://thepracticaldev.s3.amazonaws.com/i/r887jd2yo3wusmmer2il.png)

As you can see above this renders nicely and even the javascript part works as well when we click the button we get our alert window.

### A list control

Ok then, we have created our first custom control which is really cool how easy that was but we haven't shown its real value, namely - how we can interact with the front matter. 

What we will do is to create a list-control. A control that takes all the articles we have written and is able to present those in a list format. Let's do the following:

1. **Create a directory and articles**, let's create a directory for our articles and let's call it `pages` next create `typescript.md` and `vuex.md` 

2. **Add frontmatter**, let's give them each a front matter that includes title, language, publishing data, and list of keywords

2. **Create a list component**, let's create a list component that will be able to iterate over these articles, grab out the data it needs and format it nicely

**Create a directory and articles**
It should look like the below

![](https://thepracticaldev.s3.amazonaws.com/i/2gbjli8ui5st3m073zrx.png)

**Add frontmatter**
We said before this is YAML so let's try to include all the needed info we mentioned like so:

```yaml
---
title: My first article on TypeScript
lang: en-US
published: 2019-09-19
meta:
  keywords:
    - TypeScript
    - JavaScript
    - Tutorial
  description:
    content: Article on TypeScript
---
```

Above is an example of one of the articles front matter, the one called `typescript.md`. Obviously, the articles title, publishing date, keywords and description would be different for another article. We can pretty much decide how we want to structure the above, as long as it is valid YAML.

**Create a list component**

There is one thing making all this possible. Vue components placed in the `components` directory have access to a site object like so `this.$site`. That site object has property `pages` which is a list containing all the pages you have so `this.$site.pages`. 

That's awesome news, but we need to filter it a little because we only want pages in the `pages` directory. We can easily get that through the following code:

```js
return this.$site.pages
  .filter(p => {
    return p.path.indexOf('/pages/') >= 0;
});
```

Now is where our front matter comes in. Everything we define in a frontmatter of our page is being parsed as an object so when we loop through each page we have access to `page.frontmatter`. Therefore we can easily access our keywords with `page.frontmatter.meta.keywords` for example. 

This means we can keep building out our list component to look like so:

```js
// List.vue

<template>
  <div>
    <div class="article" v-for="page in files">
      <a v-bind:href="page.path">{{page.title}}</a>
      <div class="keywords">
        <span class="keyword" v-for="key in page.frontmatter.meta.keywords">{{key}}</span>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  computed: {
    files() {
      return this.$site.pages
        .filter(p => { 
          return p.path.indexOf('/pages/') >= 0;
        });
    }
  }
}
</script>
<style scoped>
  .article {
    margin-bottom: 20px;
    border-left: solid 5px #3eaf7c;
    padding: 20px;
  }
  .keywords {
    margin-top: 10px;
  }
  .keyword {
    padding: 5px;
    border-radius: 7px;
    font-size: small;
    background: #3eaf7c;
    margin-right: 5px;
    color: white;
    font-weight: 500;
  }
</style>
```

Putting it in use it will render like so:

![](https://thepracticaldev.s3.amazonaws.com/i/i1565yctim4ngty276u1.png)

Now we can definitely improve the above by making sure when we click a keyword we end up with a list of articles matching that keyword and well, the sky is the limit. I will leave that exercise up to you. You should have been given enough information to know how to continue.

## Default theme
Theming itself is a big topic so I will leave custom theming for a future article. What I will describe is how you can use the current default theme and help make your site a little better looking. 

It contains quite a lot of functionality, the full list of features is here:

> https://vuepress.vuejs.org/default-theme-config/

One thing we can change is our homepage `README.md`. We can completely change it by adding frontmatter like so:

```yaml
---
home: true
heroImage: ./logo.png
actionText: Get Started →
actionLink: /articles/
features:
- title: Blog
  details: This is a blog consisting of articles on various tech topics
- title: CV
  details: This is my CV
- title: About
  details: This tells you everything about who I am as a person
footer: MIT Licensed | Copyright © 2018-present Evan You
---
```

This will give us a *hero* part of the page, a prominent piece of information followed by three columns *features* underneath. The above YAML will render like so:

![](https://thepracticaldev.s3.amazonaws.com/i/w5xu7c68w5d2tbp913o2.png)

NOTE, we haven't discussed how we manage assets and you might be wondering how it knew how to resolve `heroImage` that pointed to `./logo.png`. We actually created a directory `public` under `.vuepress` and that's where we put our image.

I thought I would mention one more thing on our default theme and that is the menu functionality. We need to create a file `config.js` under `.vuepress` directory and make sure we set the property `themeConfig` like so:

```js
module.exports = {
  themeConfig: {
    nav: [{
        text: 'Home',
        link: '/'
      },
      {
        text: 'About',
        link: '/about/'
      },
      {
        text: 'CV',
        link: '/cv/'
      },
      {
        text: 'Blog',
        link: '/articles/'
      },
      {
        text: 'Public Speaking',
        link: '/speaking/'
      }
    ]
  }
}
```

## Summary

That was all folks. :)

We went all the way from installing a CLI to learning some useful commands like `vuepress dev` to work with it. Furthermore, we also learned about `vuepress build` that would render the finished static files. 

One of the really cool things we showed was how easy it was to create custom controls and finally, we showed how much functionality is already there when you used the default theme. 

As a personal note, this is seriously the simplest static site generator I've ever used. Can't wait for this to be even better from its already very good level. TRY IT!