How we set up automatic navigation in Docusaurus

RuStore's technical editorial team is in touch. In the last article we talked about the migration of RuStore documentation. We continue to explore the capabilities of Docusaurus and introduce you to them. Today we will discuss setting up a navigation menu in Docusaurus. With the growth of the volume of documentation, it becomes difficult to manually control the navigation, so we decided to switch to an automatic menu. In this article, we will talk about setting up an automatic navigation menu.

Where did we start?

From the very beginning, the documentation was divided into four large sections. We write in MDX, one file – one page. Each of these sections has its own navigation menu on the left side of the site.

SDK section navigation menu

SDK section navigation menu

The navigation menu is configured in the system file of the documentation engine – it can be assembled manually or automatically. Initially, it was decided to form the navigation menu manually from the abstract assumption that this would allow better control over the contents of this menu. That is, in the simplest case, the procedure for adding pages and updating the navigation menu looked like this.

  1. The writer adds a page (MD/MDX file) to the documentation structure and fills it with the desired content.

  2. After adding a page, the writer specifies a link to that page in the navigation menu file.

The line of the added page looks like this: 'sdk/rustore-geo/general/intro',

After working on the page, you need to do one more simple action: add the page to the navigation menu. Moreover, if a syntax error was made when adding or the path/file name was incorrectly specified, the engine will not allow you to build the documentation or at least run it locally in developer mode (that is, in the mode of instant display of the changes made). Automatic fuse. Debugging on the fly, and most importantly – the navigation menu is easy to control.

And, of course, it is unlikely that voluminous documentation can be limited to a single-level list of pages – one way or another, there is a need for categories. (Here and below, categories mean drop-down lists in the navigation menu.) These categories contain links to pages (for example: descriptions for specific SDK versions) and may contain subcategories. It is clear that in practice, it is unlikely that anyone will make navigation deeper than the second, or more rarely, the third, level without special need, but anything can happen.

Depending on the settings, when selecting a category, either an explicitly specified custom page (from the source MD/MDX file) or a dynamically generated page that includes general information about the category's contents (nested pages and subcategories) may be displayed. In the service file of the navigation menu, where changes must be made manually, these two types of categories are designed with minor differences.

Code for custom page in manual navigation menu:

type: 'category',
label: 'Начало работы',
link: {
  type: 'doc',
  id: 'users/start',
},
Custom Category Page

Custom Category Page

Code for dynamic category page in manual navigation menu:

type: 'category',
label: 'Как установить сборку',
link: {
  type: 'generated-index',
  slug: 'users/start/install-on-tv',
},
Dynamic Category Page

Dynamic Category Page

The syntax for creating a category is easy to remember, and you can also save the structure in a separate file or embed it in a macro and assign it to a keyboard shortcut. A new employee will easily find their way around existing examples of how to create a particular type of category (no).

It's still an automatic

In a short time, the size of the manual and well-controlled navigation grew to 1364 (one thousand three hundred sixty-four) lines. Of course, this number included lines hidden by comments – what if they come in handy? Links to pages under development could also be commented – so that they could later be added to the menu at once, removing the comment syntax. The main thing is not to forget to do this. But the main increase was due to the replenishment of documentation on tasks from product managers and development. The need to change somewhere in the middle of the navigation list required the writer to practice scrolling, tenaciously peering into the stacks of lines so as not to scroll past the necessary section.

Total:

  • the writer after working on the page must not forget specify it in the navigation file manually;

  • if a category is created, the writer must design the desired type of this category and fill it with content;

  • you always need to remember about paths and syntax – any error blocks the assembly of all documentation (the engine tells you where the error is, but it still takes some time to fix);

  • the writer must more or less navigate through more than a thousand lines of navigation file;

  • that is, in addition to actually working with the content of the page that the end user of the documentation will read, the writer must also consider whether that page needs to be added to the menu.

  • The developers are also filling out the documents – a visa for merge Of course, the writers do it, but it takes extra time to check.

For a combination of reasons, it was decided to generate the navigation menu automatically. For these purposes, a “hooligan” branch in the repository was used, created earlier for experiments and getting answers to constantly arising questions, what will happen if. (Recall that the documentation had recently moved, and the engine was new to us.)

What should be done

At first, we simply replaced the manual table of contents with an automatic one – this is what happened.

Automatic navigation menu without additional settings

Automatic navigation menu without additional settings

That is, automatic navigation repeats the file structure of the section, while:

  • categories do not have their own pages;

  • the name of the folder in the engine file system is displayed as the category name;

  • Categories and pages are displayed in alphabetical order, with:

    • the name of the folder or file in the engine's file system is taken as a basis;

    • Uppercase characters come before lowercase characters;

    • the display order does not depend on the type of menu element – category or page;

  • The names of pages in the menu are taken from the page title.

We focused the picture and the problem appeared in a clear resolution; we needed to figure out the following:

  • how to make categories have their own pages;

  • how to control the order in which navigation menu items (categories and individual pages) are displayed;

  • how to set names for navigation elements, in particular categories (it was more or less clear about pages).

All this is necessary so that an outside observer does not notice the changes after switching to the automatic navigation menu. To make it “as it was”, while getting rid of the shortcomings of the navigation assembled manually.

Theory and practice

We began to dig into the documentation engine manual in detail.

The engine documentation is arranged in a mosaic, and the necessary information is scattered across sections, often without any obvious connection. In addition, the painstaking work of the local SEO is noticeable: various search query formulations led to the same pages viewed many times, which did not provide any new information, but apparently regularly wound up the view counter. Of course, the issue of setting up the navigation menu can be considered a private case, but in any case, the entire set of information available in the documentation was incomplete.

Therefore, as the classic said: practice is the criterion of truth. And it is good when there are cats on which you can practice. This is about the branch in the repository for experiments. Information from the documentation had to be checked, and the gaps had to be filled with guesses justified by intuition and common sense, which also had to be checked. So, empirically, we identified the patterns of interest to us and ways of solving the mentioned practical problems. More on this in order below.

How to create category pages

Let me remind you that in the manual navigation menu, there were two types of category pages:

  • dynamic category pages – display information about the content of a category (page, subcategory);

  • custom category pages – custom pages are created using specific MD/MDX documentation files with their own content.

Category pages are generated by the engine based on category metadata. Metadata is specified in the file _category_.jsonwhich should be placed in the category folder. For example, we have the following documentation file structure:

/
├── tower
│   ├── genie.mdx
│   ├── giant.mdx
│   └── naga.mdx
└── nomad.mdx

In the example given there is one folder (category) towercontaining pages and a file nomad.mdxwhich will be displayed in the navigation menu as a separate item on the same level as the tower category.

So, to add metadata for toweryou need to add a file to this folder _category_.json:

/
├── tower
│   ├── category.json
│   ├── genie.mdx
│   ├── naga.mdx
│   └── giant.mdx
└── nomad.mdx

File _category_.json Depending on the desired category type, it should have the following minimum required settings.

Dynamic Category Page

"type": "generated-index" specifies that a dynamic page will be generated.

Custom Category Page

{
  "link": {
	"type": "doc",
	"id": "autogenerated/tower/naga"
  }
}
  • "type": "doc" specifies that a specific file will be used to create the category page.

  • "id" — file identifier, it can be specified in different ways, here: path from the root of the site with the file name without extension.

Wherein:

  • as a custom page, you can specify any file from the documentation file structure, even if it is not in this category;

  • If you specify a file that is in this category, it will be displayed at the category level (in this case, at the first level of the navigation menu) and will not be displayed in the drop-down list as a sub-item, i.e. there will be no duplication of the menu item.

How to set navigation element names

We've sorted out the category pages – now it's time for the displayed names of the navigation menu elements. Here, everything depends on which element is displayed:

  • separate page;

  • dynamic category page;

  • custom category page.

Separate page

As we understood above, when we first turned on automatic navigation, the title of the element of this navigation itself is displayed as the title of the page title. In Markdown, the title is specified by a hash (#). However, the MD/MDX source of a page can also contain metadata (front matter), in which you can specify parameters:

  • sidebar_label — the name displayed in the navigation menu;

  • title — page title;

  • id — page identifier that overrides the source file name in links.

In addition, the page may not have a title at all. Let's take the source file as an example nomad.mdx with the following contents:

---
sidebar_label: Nomad (sidebar label)
title: Nomad (title)
id: Nomad Id
---

# Nomad (heading lvl 1)

Lorem ipsum dolor sit amet...

## Heading lvl 2

Lorem ipsum dolor sit amet...

The engine uses the following priority (from highest to lowest) to display the navigation menu item.

Display name source

Location

How it is displayed in the navigation menu

sidebar_label

Page Metadata

Nomad (sidebar label)

title

Page Metadata

Nomad (title)

First level heading #

Page body

Nomad (heading lvl 1)

id

Page Metadata

Nomad Id

File name without extension .md/.mdx

File system

nomad

Markdown headings of level 2 and deeper are not taken into account.

Dynamic Category Page

It's much simpler here. The parameter value is used to display the category name label in category metadata (file _category_.json):

{ 
  "label": Tower (category label),
    "link": {
      "type": "generated-index"
    }
}

If this parameter is not specified, the folder name in the documentation file structure is used. That is, the priority is as follows:

Display name source

Location

How it is displayed in the navigation menu

label

category metadata

Tower (label)

Folder name

file system

tower

Custom Category Page

As you might expect, in this case the category name is displayed based on a combination of the two previous rules. Metadata of a category located in a folder tower:

{
  "label": Naga (category label),
  "link": {
    "type": "doc",
      "id": "Naga Id"
  }
}

Page Contents naga.mdx, which is used as a category page:

---
sidebar_label: Naga (sidebar label)
title: Naga (title)
id: Naga Id
---

# Naga (heading lvl 1)

# Naga

Lorem ipsum dolor sit amet...

Note! In the parameter id category metadata (_category_.json) the value specified in is indicated id file metadata naga.mdx.

Below is a table of category display name source priorities.

Display name source

Location

How it is displayed in the navigation menu

label

category metadata

Naga (category label)

sidebar_label

page metadata

Naga (sidebar label)

title

page metadata

Naga (title)

First level heading #

body of the page

Naga (heading lvl 1)

id

page/category metadata

Naga Id

File name without extension .md/.mdx.

file system

naga

How to control the display order of navigation items

As mentioned earlier, by default, without any additional settings, the engine arranges pages and categories in alphabetical order of file and folder names, with uppercase characters sorted before lowercase characters. That is, all files/folders whose names begin with an uppercase character are displayed above all files/folders whose names begin with a lowercase character in the menu. Pages are sorted equally with categories (see below).

File structure:

/
├── fortress
│   ├── basilisk.mdx
│   ├── gorgon.mdx
│   └── Hydra.mdx
├── Stronghold
│   ├── behemoth.mdx
│   ├── Goblin.mdx
│   └── Ogre.mdx
├── nomad.mdx
├── sharpshooter.mdx
└── Troll.mdx

Display order in the navigation menu:

  • Stronghold

  • Troll

  • fortress

  • nomad

  • sharpshooter

So how do you control the order in which items are displayed? The engine has a system of “weighting” the navigation menu elements that is familiar to many. Thus, a page/category with a “weight” of 1 is located in the menu above a page/category with a “weight” of 2 – an easily learned principle. And although, of course, by the time the navigation menu was switched to automatic mode, it was still necessary to provide for the possibility that a new item would need to be wedged into the middle of the menu. Therefore, after a little brainstorming, it was decided to use “weights” of 10, 20, 30, and so on.

So, to add a new item to the end of the navigation menu, you need to add +10 “weight” from the previous one. If you need to insert an item in the middle (say, between 40 and 50), you should use the value 45, between 40 and 45, use 43, etc.

What if there is a need to expand the menu even more? Or hang the item above the first one? The engine documentation does not explicitly state this, but the engine allows you to use:

Looking ahead, I will say that negative values ​​and fractions will come in handy later.

Thus, when using mixed sorting, the following prioritization is applied:

  • sorting by explicitly specified “weights” of the navigation menu item;

  • alphabetical sorting by file/folder names – uppercase characters;

  • alphabetical sorting – lowercase characters.

Thus, any navigation menu item with an explicitly specified “weight” will be higher than any item where this “weight” is not specified. The “weight” parameter depends on what it is set for: for a page or for a category:

  • the page metadata uses a parameter sidebar_position;

  • the category metadata uses the parameter position.

See below for details.

Separate page

The “weight” of a page is indicated in its metadata:

---
sidebar_position: 10
---

The sorting priority is shown below:

Criterion

Location

sidebar_position

page metadata

A file name starting with an uppercase character.

file system

File name starting with a lowercase character

file system

Dynamic Category Page

Example of category metadata (_category_.json):

{
  position: 20,
  "label": Tower (category label),
  "link": {
     "type": "generated-index"
     }
}

The sorting priority is shown below:

Criterion

Location

position

category metadata

The name of the category folder, starting with an uppercase character.

file system

The name of the category folder, starting with a lowercase character.

file system

Custom Category Page

Here, as with the page name, the position can be defined in the category metadata or in the page metadata. Example of category metadata (_category_.json):

{
  position: 30,
  "label": Naga (category label),
  "link": {
    "type": "doc",
    "id": "Naga Id"
    }
}

Example of custom category page metadata:

---
sidebar_position: 0
id: Naga Id
---

The sorting priority is shown below:

Criterion

Location

position

category metadata

sidebar_position

page metadata

The name of the category folder, starting with an uppercase character.

file system

Category folder name starting with a lowercase character

file system

Note!

  • If you delete position from category metadata (_category_.json), then this category from the third place will rise above all categories where a positive “weight” is indicated – since 0 precedes the values ​​10 and 20.

  • If you remove the “weight” both in the category and on the page, then the category folder name is taken into account for alphabetical sorting – the page file name is not taken into account.

What happened in the end

So, it seems that everything is set up: the names of the menu items are displayed as they should be and are arranged in the right order. The categories have their own pages – “as it was”. In theory, you can carefully replace the manual menu with an automatic one and live happily. However, as often happens, additional actions were required. This, as well as general considerations regarding automatic navigation – in the next part of the article.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *