How to create a custom VuePress theme with Vuetify

If you’ve heard of VuePress already you might know that it’s a powerfully minimal static site generator by Vue.js Creator Evan You. VuePress makes the creation of text-heavy documentation websites easy, a lot easier than Nuxt.js.

But, did you know that VuePress has a custom theme system built on top of Vue that lets you build your own fully featured themes with custom functionality?

In this article, we’ll go over how you can get started creating your own custom theme, some best practices to follow, and how to integrate a UI pattern library like Vuetify for fast layout creation.

For example, let’s take the VuePress documentation website itself. It’s using the default theme. The default theme comes out of the box with a lot of custom functionality like a built-in search, customizable nav and sidebars, and even an auto-generated GitHub link and page-edit links that are great if you’re hosting your website using GitHub Pages.

The VuePress website

You’ll be able to build themes just as featured as the default theme. If you’ve used Vue.js for development before, you will see that the development experience is similar when you’re creating a custom theme. You can even use Vue DevTools to debug your custom theme.

So let’s get started.

Setting up a VuePress project

First, make sure that you have VuePress installed on your system.

npm install -g vuepress

Create a folder for your VuePress website with the following command: mkdir my-vuepress-project.

Click here to learn more about integrating VuePress with an existing project.

Structuring your content

The beauty of VuePress is that it allows you to structure your content however you like. Every single markdown file in your project will be compiled into a static HTML file.

For example, your project might be structured something like the following:

So once your project has content, how do you start creating a custom theme to display that content?

Creating your custom VuePress theme

In the folder structure example above you might have noticed a folder named .vuepress. This folder is where your configuration and all VuePress-specific files go. It’s also where your custom theme files will go.

To create a custom theme, create a theme directory inside of the .vuepress directory in your VuePress project, and then create a Layout.vue file.

The Layout.vue component

The Layout.vue component is the file that VuePress looks for when invoking your theme. It will be invoked once for every markdown file in your VuePress project.

For example, it will be invoked 4 times with our example structure, which has four markdown (.md) files.

Rendering your website’s content inside of your theme.

The simplest theme can be just a single Layout.vue component with the following markup:

The compiled content of the current .md file being rendered will be available as a special <Content/> global component.

Another way to think about the Layout.vue file is as the starting point for your theme because in reality, a fully fleshed out theme will require more than just a single file.

Structuring your VuePress theme

So what’s the recommended structure for a custom VuePress theme? There are no enforced rules, but many themes out in the wild are structured something like the following:

This structure allows you to organize your individual page layouts (like your Post and Home pages) in the layouts folder, and then have your individual components (that those layouts use) in the components folder.

Integrate a UI pattern library like Vuetify into your custom theme

Ultimately, VuePress custom themes are just Vue applications so you can do anything that you would normally do inside of your applications. For example, you can include a UI pattern library into your custom theme from npm.

From the terminal, cd into your .vuepress folder and then do an npm install vuetify — save in order to get Vuetify into your custom theme.

Now you can take full advantage of any library inside of your theme and can fully customize your theme files.

Home.vue

Post.vue

Customizing your theme with your page’s data

Once you have a folder structure in place and have laid out your individual layout components, how do you get those individual components to render from Layout.vue?

When it comes to your individual markdown files, VuePress gives you a lot of customization options. You can add YAML front-matter, a data serialization language commonly used for configuration, at the top of your markdown files and VuePress will automatically interpret it for you.

Each time Layout.vue is called, the YAML that you have defined in your file, along with other VuePress-generated metadata, will be available inside of your Layout.vue component as this.$page.

For example, when processing your /guides/getting-started.md file then your this.$page variable might look something like the following:

{
"lastUpdated": 1524847549000,
"path": "/guides/getting-started.html",
"title": "Guides - Getting Started",
"frontmatter": {}
}

You can then use that data to customize the theme to your liking. For example, one thing you might do is render a different HTML / CSS layout for a different look depending on the path of the file.

Another variable that is injected is this.$site that gives you information about your entire website.

{
"title": "VuePress",
"description": "Vue-powered Static Site Generator",
"base": "/",
"pages": [
{
"lastUpdated": 1524027677000,
"path": "/",
"title": "VuePress",
"frontmatter": {}
},
...
]
}

One example of what you can do with the this.$site.pages array is looping through it and creating next and previous links.

The this.$site and this.$page properties are injected into every component inside of the .vuepress folder.

Click here to learn more about all of the data that is injected into your components.

Extra Resources

Here are three custom VuePress themes up on GitHub that you can use as a reference to creating your own.

Or, you can just install them directly.

Click here to learn how to install these themes directly into your project.

Conclusion

Ultimately, creating a VuePress theme gives you just as much flexibility as creating a Vue.js app. You’re free to lay out your theme in the way that works best for you.

In this post, we went over some best practices, the data that you can use inside your theme components, and also how to integrate with a UI library like Vuetify for creating layouts.

Keep Reading