In-Depth VuePress Tutorial: Vue-Powered Docs & Blog

In a rush? Skip to technical tutorial or live demo.

Have you ever skimmed through the Vue.js documentation?

Anyone familiar with it will tell you:

It's magnificent.

To build it, Evan You, Vue's creator, came up with VuePress.

For an upcoming side project of ours, we decidedly wanted some of that docs' magic. This post is an account of that process.

You'll learn what VuePress is, what's so great about it, and how to quickly set up a neat Vue.js-powered documentation & blog.

Steps for the technical tutorial:

  1. Installing VuePress.

  2. Generating documentation content.

  3. Adding a blog to VuePress.

  4. Inserting the blog in the navigation.

It's easy & straightforward—you'll be done in no time.

A bit of context for our VuePress project

What's this side project I'm talking about? Well, it started with a pain any blog editor or webmaster knows too well:

Cringe-worthy outreach emails.

You know the kind of email that praises your blog content and offers some guest posts about real estate... on a WEB DEVELOPMENT platform?!

We thought it was time to put a spotlight on this stinky marketing technique. To do so, we built a simple Hugo static site where anyone can publish anonymous and funny examples of how not to outreach. The name of the site? Outreach Shame.

Note: Outreach Shame isn't live yet, but it presented us with a good use case to build VuePress documentation. You'll find real guidelines in the documentation we created (link further down). Follow them to send us your lousy outreach examples; they'll appear on the site once it goes live.

What is VuePress?

In a few words, VuePress is a minimalistic Vue-powered static site generator.

As mentioned earlier, the original goal behind its design was to generate documentation, but its system also allows you to write a theme for almost anything.

I've read in a few places that VuePress is not blog-aware yet. Although it does miss some blogging features out-of-the-box, it's still well-suited for simple blogs, as you'll see later on.

VuePress is only a few months old but has already made some waves mainly because it comes directly from the brain behind Vue.js. Let's see what the man has to say about VuePress:

"It’s special in the sense that it completely uses Vue for its layout and because Vue is a frontend framework it’s actually using a few server-side rendering capabilities to do the static HTML generation. The result is, when you write your layout or your theme for a VuePress site it’s actually a universal application that runs both on the server and on the client."

The server is skipped though, and every route of the app is virtually rendered to generate static HTML files that load as a Vue.js single page application.

Why should you use VuePress?

As you're probably aware, there are tons of static site generators out there. So where does VuePress stand out?

Its unique use of Markdown & Vue components

VuePress handles the conversion of Markdown to HTML by default which makes generating new content very easy. You can even use Vue components directly in your Markdown files. It allows you to add custom or dynamic features to your website smoothly. Other built-in Markdown features include a YAML front-matter to set predefined variables or create custom ones that VuePress will automatically interpret.

Its multi-language support from the get-go

Out-of-the-box, VuePress lets you write several versions of your site in as many languages as you need. (!)

Its neat default & custom themes

The least I can say is that the VuePress default theme looks clean. It'll do the job for any fast implementation of technical documentation. It's responsive & fully-featured (search capabilities, navbar & sidebar, optional homepage, etc.). Then, customizing the default theme or starting from scratch is simple and fun.

Why VuePress over Nuxt.js for a Vue SPA?

If you're into the whole Vue.js ecosystem you surely already know about the framework for universal apps that is Nuxt.js. It's way more than a SSG, but its nuxt generate feature allows you to create a static version of an app. VuePress was actually inspired by that exact feature.

Both have very different goals. Everything you can do in VuePress you'll also be able to achieve with Nuxt.js. VuePress simplifies the things its good at though, which for the moment include documentation & very small SPAs. If that's all you need, VuePress works wonders, while Nuxt.js might quickly feel overkill.

On the other hand, you couldn't use VuePress for any real app development. There's no debate you should go with Nuxt.js here.

Nuxt.js is often mentioned as a great tool to handle Vue.js SPA SEO issues. Turns out VuePress does the same to ensure that all content is rendered and crawlable by search engines.

Anyway, let's see how it went! ;)

VuePress tutorial: Crafting documentation & blog platform

For my use case, I'll go on and use VuePress for Outreach Shame's documentation. While I'm at it, why not add a blog to support the project as well?


  • A npm installation

  • A basic understanding of Vue.js

1. Installing VuePress

VuePress is a Node application that needs to be installed via npm or yarn.

Open a terminal and type:

npm i -g vuepress

VuePress will then be available directly in your command line. Two useful commands here:

  • vuepress dev starts a development server with automatic reload and all the dev goodies. This is the command you'll use when developing your website.

  • vuepress build builds your website. The generated assets will be ready to deploy on any hosting service.

2. Generating documentation content

You can add VuePress to any repository with a file. This is why VuePress' main selling point is cleaner documentation.

At the root of your project, create a file. It's going to be your site index, the home page. My content:

# Outreach shame
Outreach Shame is the place to expose every lousy outreach emails. It’s every online marketer’s worst nightmares. These emails are everything you shouldn’t do to promote your business & content. Everything’s kept anonymous for good fun above all.

## How can you contribute?
Simple, forward us the shameful email to ** where it’ll be up for moderation. We kindly ask you to censor any personal information from the email before forwarding it to us. Once your submission is accepted by our team it’ll be published on the site

## How it does work?
Once a submission is approved, a commit is pushed in this [GitHub repository]( We then use [Forestry]( to make content editing and publishing easier for our dumb marketing folks. Once the entry is published, the site is built and deployed automatically on Netlify.

Then, start your development server:

vuepress dev

When VuePress is ready, open a browser and navigate to http://localhost:8080.

You will see your website with the classy default VuePress theme.

It'd be nice to have a title in the navbar, right?

Well, customizing the default VuePress theme with quick configurations is easy peasy.

Start by creating a folder named .vuepress at the root of your project's folder. In this folder, add a file named config.js. This file will be used to customize the website; it's basically a JavaScript file that should export a JSON object.

// /.vuepress/config.js

module.exports = {
    title: 'Outreach Shame'

If you reload your website, you'll see the title in the top left corner of the navbar.

3. Adding a blog to VuePress

As you can see, it's a walk in the park to build custom documentation for a project using VuePress. So let's push it further a bit and add a blog.

As I wrote earlier, VuePress allows you to write custom Vue components that can be inserted into any Markdown files. In this case, I'll build a component that will render the list of blog posts.

Create a folder named components in the .vuepress folder. You'll add your components in there. They'll then be automatically available globally; no need to import them.

Somehow VuePress has it covered.

Create a file named BlogIndex.vue—VuePress components use the single file component pattern.

A component created in a VuePress application gets some computed properties out of the box. You can access this.$site which gives you metadata of the website, with each page in it. This is going to be useful in this case because this is how we'll get the blog posts.

You also have this.$page giving you information about the current page context.

Here is the code you will need in your component file:

<!-- /.vuepress/components/BlogIndex.vue -->

    <div v-for="post in posts">
            <router-link :to="post.path">{{ post.frontmatter.title }}</router-link>
        <p>{{ post.frontmatter.description }}</p>

        <p><router-link :to="post.path">Read more</router-link></p>

export default {
    computed: {
        posts() {
            return this.$site.pages
                .filter(x => x.path.startsWith('/blog/') && !x.frontmatter.blog_index)
                .sort((a, b) => new Date( - new Date(;

The template itself is pretty basic. I iterated through the list of posts and listed them all. I'm using the router-link component available through vue-router that VuePress comes equipped with.

I added a computed property named posts. This property gets all the blog posts from the site pages. When you create new blog posts, you'll need to specify some front matter information, such as the post date. Newest posts will appear first.

The component is ready! Now you'll need to add some content.

Create a folder named blog at the root of the project. In this folder, add a file. This is going to be the blog index, and this is where you'll include the BlogIndex component.

blog_index: true

# Blog

Welcome on Outreach shame blog

<BlogIndex />

The blog_index front matter will be used to make sure that the blog index isn't listed in the posts. I'm using it when filtering the posts in the posts computed property of the BlogIndex component.

Notice how easy it is to include a custom component. It's registered automatically by VuePress and can be included in any markdown file.

Next step is to add a first blog post. In the blog folder, create a filed named

You'll have to define a couple of frontmatter settings:

<!-- /blog/ -->
title: Bacon ipsum dolor amet hamburger pancetta ball tip
date: 2018-07-28
    Kielbasa tenderloin boudin bacon cupim, pastrami strip steak rump picanha meatloaf venison meatball ribeye. Burgdoggen t-bone jowl venison biltong andouille. Turducken shankle tongue landjaeger drumstick, pancetta porchetta. Brisket ham turkey andouille picanha. Pancetta chuck shank ham.

# First post

/* Your awesome content goes here */

The properties title, description and date are important; they will be used when listing blog posts. Every post in the blog folder should have these defined.

4. Inserting the blog in the VuePress navigation

The last step will be to make the blog available via the navigation bar.

Open /.vuepress/config.js file again and add:

// /.vuepress/config.js

module.exports = {
    title: 'Outreach Shame',
    themeConfig: {
        nav: [
            { text: 'Home', link: '/' },
            { text: 'Blog', link: '/blog/' }

You'll need to specify the nav bar elements in the themeConfig property.

Then, reload your website and click on the blog navigation item, you should have something like this:

Live demo & GitHub repo

See the live demo here

See GitHub repo here

Closing thoughts

VuePress is so awesomely straightforward. I only spent around two hours building this demo, and that includes learning how VuePress works. It might just be the best tool out there to document your open source project or library.

Having the ability to use Vue components on top of that is a huge bonus. We're currently working on the third version of our shopping cart and this experiment forces me to seriously consider using VuePress to build its documentation!

However, as working with it confirmed, I don't think you should use VuePress to build applications. Frameworks like Nuxt and Gatsby would be better options to develop a more complex application.

If you've enjoyed this post, please take a second to share it on Twitter. Got comments, questions? Hit the section below!

About the author

Charles Ouellet
Co-Founder & Product Owner

Charles has been coding for over 16 years (if we count his glory days with HTML/PHP). He's the founder and lead developer behind Snipcart and has spoken at several web development events including the WAQ, VueToronto and WinnipegJS. Formerly a backend programmer, he's now fluent in JavaScript, TypeScript, and Vue.js. Charles is also a big believer in the Jamstack.

Follow him on Twitter.

An Easy Guide to Enhanced Ecommerce Analytics with Google Tag Manager

Read next from Charles
View more

36 000+ geeks are getting our monthly newsletter: join them!