This page looks best with JavaScript enabled

Automatic Dynamic Sidebars in Vuepress

 ·   ·  ☕ 6 min read

How can you get automatic sidebars to be generated in Vuepress depending on the page?

The Situation

Vuepress is simple.

Being simple is rather difficult. In the case of Vuepress, the difficulty can show up in unexpected places.

Starting with Vuepress is simple enough. Equally simple is enabling navigation on your site at multiple levels through a “sidebar” and/or a “navbar”. Specifically for the sidebar - you can enable in by adding a couple of lines in /docs/.vuepress/config.js.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
module.exports = {
  //...
  themeConfig: {
    sidebar: [
      { title: "Home", children: [""] },
      {
        title: "Misc",
        children: ["more"],
      },
    ],
  },
  //...
};

The above change will create a sidebar for your site with links under Home and Misc. The title of links will be either -

  • the title of the page (or)
  • the first header element within the markdown files that the links point to

This is how it looks -

vuepress-site-navbar-sidebar

As you can see: the H2 headers will be links grouped below the file links.

But, what if you need to do more -

  1. you want to create different sidebars for different pages. For e.g. if you are creating a site that has a bunch of different guides instead of one guide with multiple chapters. When you go to specific pages (which are represented as folders in Vuepress root folder), the navigation links have to change to point to different markdown files in a specific folder
  2. you may want to continue having H2 behaviour be Vuepress default - show the links within the specific markdown files
  3. you don’t want to write links to all the files by hand. Instead you want the system to automatically “see” the content to be linked

In a recent project I needed the “Admin”, “Developer” and other folders to have their own sidebars with navigation links. -

vuepress-dynamic-sidebar-appearance

This sidebar is slightly different from Vuepress default, which seemingly assumes that all of the content is one big happy family. Vuepress by default enables links just point to the different markdown files in the document root, and to the H2 elements when the parent links are expanded.

Solutions

Let’s look at how we can customise sidebar in Vuepress.

Vuepress is after all powered by Vue - so customisation is not really a complex problem. However, I did not find this as straight forward as something like Gridsome. In Gridsome you just create a component for navigation like any sane developer and the system will exactly do what it has to - render the navbar.

Vuepress’s navbar is driven by config (and if applicable, plugins) - so this seemed not so elegant(!?) at first. But as always - all you need to solve world’s problems are good docs and some time.

Given below are three solutions that I tried to different degrees of success. The solution that worked for me is at the end because I am heartless and believe in making people scroll.

Solution 1. Use vuepress-plugin-auto-sidebar plugin

The plugin vuepress-plugin-auto-sidebar seemed to do exactly what I wanted.

To install a plugin in Vuepress, all you have to do is -

  1. Install the package using npm/yarn
  2. Use the plugin in config

Let’s get this going. Go to Vuepress folder and install package.

1
npm install --save vuepress-plugin-auto-sidebar

Include plugin in /docs/.vuepress/config.js-

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
module.exports = {
  // ...
  plugins: {

"vuepress-plugin-auto-sidebar": {
      titleMap: {
        "salesforce-for-students": "Salesforce for Students",
        "pd1-guide": "Platform Developer I Certification Guide",
        "admin-guide": "Admin Certification Guide",
        "why-learn-salesforce": "Why Learn Salesforce?",
        misc: "Miscellany"
      }
    },
// ...
}

This configuration will provide custom titles for the different folders and automatically pick up the files within the folder to create distinct, dynamic navigation bars.

In the ideal world, this should have been it and I should not have been sitting around to create a blog post about all the circus. But hey - ideal world is not exciting.

  1. Getting started was bit of a bother. The documentation of the package is in Chinese and there are not many examples. Google translation helped to an extent
  2. I could not quite figure out how autoNext and autoPrev worked. My files were not exactly sorted in the folder and sort order of the links in the sidebar was messed up
  3. There were random failures. You could never say when sidebars generation failed (silently), and for the life of me, I could not figure out why. With dozens of files in different folders, I was quite frustrated with all the cut/pasting of content just to see what caused the program to fail
  4. If you have a sub-folder with a README in the root, the README does not show in the navigation. This is expected as per Vuepress, but I could never say when the README appeared as a separate link and when it wouldn’t

Solution 2: Use vuepress-bar

vuepress-bar was another ready solution that seemed promising.

First, install the package.

1
npm i --save vuepress-bar

Next, include the plugin in /docs/.vuepress/config.js -

1
2
3
4
5
6
7
const getConfig = require("vuepress-bar");

module.exports = {
  themeConfig: {
    ...getConfig(`${__dirName}/..`),
  },
};

That’s it - you should have the new sidebars working. This worked more reliably than solution (1), but I could not figure out how to generate distinct sidebars for indidvidual content folders. All links appeared under one title - which was not ideal for my case.

vuepress-bar-sidebar

Consider using this library if you just want a dynamic sidebar (and/or a navbar).

Solution 3: Go custom

My final solution was just doing everything myself. This was not as scary as it initially appeared - all it took was a couple of lines of code.

Get started by doing changes in /docs/.vuepress/config.js -

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
const fs = require("fs");
const path = require("path");

module.exports = {
  //...
  themeConfig: {
    sidebar: {
      "/why-learn-salesforce/": getSideBar(
        "why-learn-salesforce",
        "Why Salesforce?"
      ),
      "/admin-guide/": getSideBar("admin-guide", "Admin Certification Guide"),
      "/pd1-guide/": getSideBar("pd1-guide", "PD1 Certification Guide"),
      "/salesforce-for-students/": getSideBar(
        "salesforce-for-students",
        "Salesforce for Students"
      ),
    },
  },
  //...
};

function getSideBar(folder, title) {
  const extension = [".md"];

  const files = fs
    .readdirSync(path.join(`${__dirname}/../${folder}`))
    .filter(
      (item) =>
        item.toLowerCase() != "readme.md" &&
        fs.statSync(path.join(`${__dirname}/../${folder}`, item)).isFile() &&
        extension.includes(path.extname(item))
    );

  return [{ title: title, children: ["", ...files] }];
}

And voila, you have the brand new sidebar -

vuepress-sidebar-auto-generate-function

You can see that -

  1. There’s a distinct sidebar for each folder - first level links are the files within the folder
  2. Links to README and other files are consistent
Stay in touch!
Share on

Prashanth Krishnamurthy
WRITTEN BY
Prashanth Krishnamurthy
Technologist | Creator of Things