Skip to main content
Version: 2.0.0-beta.8

Sidebar

Creating a sidebar is useful to:

  • Group multiple related documents
  • Display a sidebar on each of those documents
  • Provide a paginated navigation, with next/previous button

To use sidebars on your Docusaurus site:

  1. Define a file that exports a sidebar object.
  2. Pass this object into the @docusaurus/plugin-docs plugin directly or via @docusaurus/preset-classic.
docusaurus.config.js
module.exports = {
presets: [
[
'@docusaurus/preset-classic',
{
docs: {
sidebarPath: require.resolve('./sidebars.js'),
},
},
],
],
};

Default sidebar

By default, Docusaurus automatically generates a sidebar for you, by using the filesystem structure of the docs folder:

sidebars.js
module.exports = {
mySidebar: [
{
type: 'autogenerated',
dirName: '.', // generate sidebar slice from the docs folder (or versioned_docs/<version>)
},
],
};

You can also define your sidebars explicitly.

A sidebar is a tree of sidebar items.

type Sidebar =
// Normal syntax
| SidebarItem[]

// Shorthand syntax
| Record<
string, // category label
SidebarItem[] // category items
>;

A sidebars file can contain multiple sidebar objects.

type SidebarsFile = Record<
string, // sidebar id
Sidebar
>;

Example:

sidebars.js
module.exports = {
mySidebar: [
{
type: 'category',
label: 'Getting Started',
items: ['doc1'],
},
{
type: 'category',
label: 'Docusaurus',
items: ['doc2', 'doc3'],
},
],
};

Notice the following:

  • There is a single sidebar mySidebar, containing 5 sidebar items
  • Getting Started and Docusaurus are sidebar categories
  • doc1, doc2 and doc3 are sidebar documents
tip

Use the shorthand syntax to express this sidebar more concisely:

sidebars.js
module.exports = {
mySidebar: {
'Getting started': ['doc1'],
Docusaurus: ['doc2', 'doc3'],
},
};

Using multiple sidebars

You can create a sidebar for each set of Markdown files that you want to group together.

tip

The Docusaurus site is a good example of using multiple sidebars:

Example:

sidebars.js
module.exports = {
tutorialSidebar: {
'Category A': ['doc1', 'doc2'],
},
apiSidebar: ['doc3', 'doc4'],
};
note

The keys tutorialSidebar and apiSidebar are sidebar technical ids and do not matter much.

When browsing:

  • doc1 or doc2: the tutorialSidebar will be displayed
  • doc3 or doc4: the apiSidebar will be displayed

A paginated navigation link documents inside the same sidebar with next and previous buttons.

Understanding sidebar items

SidebarItem is an item defined in a Sidebar tree.

There are different types of sidebar items:

  • Doc: link to a doc page, assigning it to the sidebar
  • Ref: link to a doc page, without assigning it to the sidebar
  • Link: link to any internal or external page
  • Category: create a hierarchy of sidebar items
  • Autogenerated: generate a sidebar slice automatically

Use the doc type to link to a doc page and assign that doc to a sidebar:

type SidebarItemDoc =
// Normal syntax
| {
type: 'doc';
id: string;
label: string; // Sidebar label text
className?: string; // Class name for sidebar label
}

// Shorthand syntax
| string; // docId shortcut

Example:

sidebars.js
module.exports = {
mySidebar: [
// Normal syntax:
{
type: 'doc',
id: 'doc1', // document id
label: 'Getting started', // sidebar label
},

// Shorthand syntax:
'doc2', // document id
],
};

The sidebar_label markdown frontmatter has a higher precedence over the label key in SidebarItemDoc.

note

Don't assign the same doc to multiple sidebars: use a ref instead.

Use the ref type to link to a doc page without assigning it to a sidebar.

type SidebarItemRef = {
type: 'ref';
id: string;
};

Example:

sidebars.js
module.exports = {
mySidebar: [
{
type: 'ref',
id: 'doc1', // Document id (string).
},
],
};

When browsing doc1, Docusaurus will not display the mySidebar sidebar.

Use the link type to link to any page (internal or external) that is not a doc.

type SidebarItemLink = {
type: 'link';
label: string;
href: string;
className?: string;
};

Example:

sidebars.js
module.exports = {
myLinksSidebar: [
// External link
{
type: 'link',
label: 'Facebook', // The link label
href: 'https://facebook.com', // The external URL
},

// Internal link
{
type: 'link',
label: 'Home', // The link label
href: '/', // The internal path
},
],
};

Use the category type to create a hierarchy of sidebar items.

type SidebarItemCategory = {
type: 'category';
label: string; // Sidebar label text.
items: SidebarItem[]; // Array of sidebar items.
className?: string;

// Category options:
collapsible: boolean; // Set the category to be collapsible
collapsed: boolean; // Set the category to be initially collapsed or open by default
};

Example:

sidebars.js
module.exports = {
docs: [
{
type: 'category',
label: 'Guides',
collapsible: true,
collapsed: false,
items: [
'creating-pages',
{
type: 'category',
label: 'Docs',
items: ['introduction', 'sidebar', 'markdown-features', 'versioning'],
},
],
},
],
};
tip

Use the shorthand syntax when you don't need category options:

sidebars.js
module.exports = {
docs: {
Guides: [
'creating-pages',
{
Docs: ['introduction', 'sidebar', 'markdown-features', 'versioning'],
},
],
},
};

Collapsible categories

We support the option to expand/collapse categories. Categories are collapsible by default, but you can disable collapsing with collapsible: false.

sidebars.js
module.exports = {
docs: [
{
type: 'category',
label: 'Guides',
items: [
'creating-pages',
{
type: 'category',
collapsible: false,
label: 'Docs',
items: ['introduction', 'sidebar', 'markdown-features', 'versioning'],
},
],
},
],
};

To make all categories non-collapsible by default, set the sidebarCollapsible option in plugin-docs to false:

docusaurus.config.js
module.exports = {
presets: [
[
'@docusaurus/preset-classic',
{
docs: {
sidebarCollapsible: false,
},
},
],
],
};
note

The option in sidebars.js takes precedence over plugin configuration, so it is possible to make certain categories collapsible when sidebarCollapsible is set to false globally.

Expanded categories by default

Collapsible categories are collapsed by default. If you want them to be expanded on first render, you can set collapsed to false:

sidebars.js
module.exports = {
docs: {
Guides: [
'creating-pages',
{
type: 'category',
label: 'Docs',
collapsed: false,
items: ['markdown-features', 'sidebar', 'versioning'],
},
],
},
};

Similar to collapsible, you can also set the global configuration options.sidebarCollapsed to false. Individual collapsed options in sidebars.js will still take precedence over this configuration.

docusaurus.config.js
module.exports = {
presets: [
[
'@docusaurus/preset-classic',
{
docs: {
sidebarCollapsed: false,
},
},
],
],
};
caution

When a category has collapsed: true but collapsible: false (either through sidebars.js or through plugin configuration), the latter takes precedence and the category is still rendered as expanded.

Docusaurus can create a sidebar automatically from your filesystem structure: each folder creates a sidebar category.

An autogenerated item is converted by Docusaurus to a sidebar slice: a list of items of type doc and category.

type SidebarItemAutogenerated = {
type: 'autogenerated';
dirName: string; // Source folder to generate the sidebar slice from (relative to docs)
};

Docusaurus can generate a sidebar from your docs folder:

sidebars.js
module.exports = {
myAutogeneratedSidebar: [
{
type: 'autogenerated',
dirName: '.', // '.' means the current docs folder
},
],
};

You can also use multiple autogenerated items in a sidebar, and interleave them with regular sidebar items:

sidebars.js
module.exports = {
mySidebar: [
'intro',
{
type: 'category',
label: 'Tutorials',
items: [
'tutorial-intro',
{
type: 'autogenerated',
dirName: 'tutorials/easy', // Generate sidebar slice from docs/tutorials/easy
},
'tutorial-medium',
{
type: 'autogenerated',
dirName: 'tutorials/advanced', // Generate sidebar slice from docs/tutorials/hard
},
'tutorial-end',
],
},
{
type: 'autogenerated',
dirName: 'guides', // Generate sidebar slice from docs/guides
},
{
type: 'category',
label: 'Community',
items: ['team', 'chat'],
},
],
};

Autogenerated sidebar metadatas

By default, the sidebar slice will be generated in alphabetical order (using files and folders names).

If the generated sidebar does not look good, you can assign additional metadatas to docs and categories.

For docs: use additional frontmatter:

docs/tutorials/tutorial-easy.md
---
sidebar_label: Easy
sidebar_position: 2
---

# Easy Tutorial

This is the easy tutorial!

For categories: add a _category_.json or _category_.yml file in the appropriate folder:

docs/tutorials/_category_.json
{
"label": "Tutorial",
"position": 3,
"className": "red"
}
docs/tutorials/_category_.yml
label: 'Tutorial'
position: 2.5 # float position is supported
collapsible: true # make the category collapsible
collapsed: false # keep the category open by default
info

The position metadata is only used inside a sidebar slice: Docusaurus does not re-order other items of your sidebar.

Using number prefixes

A simple way to order an autogenerated sidebar is to prefix docs and folders by number prefixes:

docs
β”œβ”€β”€ 01-Intro.md
β”œβ”€β”€ 02-Tutorial Easy
β”‚Β Β  β”œβ”€β”€ 01-First Part.md
β”‚Β Β  β”œβ”€β”€ 02-Second Part.md
β”‚Β Β  └── 03-End.md
β”œβ”€β”€ 03-Tutorial Hard
β”‚Β Β  β”œβ”€β”€ 01-First Part.md
β”‚Β Β  β”œβ”€β”€ 02-Second Part.md
β”‚Β Β  β”œβ”€β”€ 03-Third Part.md
β”‚Β Β  └── 04-End.md
└── 04-End.md

To make it easier to adopt, Docusaurus supports multiple number prefix patterns.

By default, Docusaurus will remove the number prefix from the doc id, title, label and URL paths.

caution

Prefer using additional metadatas.

Updating a number prefix can be annoying, as it can require updating multiple existing markdown links:

docs/02-Tutorial Easy/01-First Part.md
- Check the [Tutorial End](../04-End.md);
+ Check the [Tutorial End](../05-End.md);

Customize the sidebar items generator

You can provide a custom sidebarItemsGenerator function in the docs plugin (or preset) config:

docusaurus.config.js
module.exports = {
plugins: [
[
'@docusaurus/plugin-content-docs',
{
sidebarItemsGenerator: async function ({
defaultSidebarItemsGenerator,
numberPrefixParser,
item,
version,
docs,
}) {
// Example: return an hardcoded list of static sidebar items
return [
{type: 'doc', id: 'doc1'},
{type: 'doc', id: 'doc2'},
];
},
},
],
],
};
tip

Re-use and enhance the default generator instead of writing a generator from scratch.

Add, update, filter, re-order the sidebar items according to your use-case:

docusaurus.config.js
// Reverse the sidebar items ordering (including nested category items)
function reverseSidebarItems(items) {
// Reverse items in categories
const result = items.map((item) => {
if (item.type === 'category') {
return {...item, items: reverseSidebarItems(item.items)};
}
return item;
});
// Reverse items at current level
result.reverse();
return result;
}

module.exports = {
plugins: [
[
'@docusaurus/plugin-content-docs',
{
sidebarItemsGenerator: async function ({
defaultSidebarItemsGenerator,
...args
}) {
const sidebarItems = await defaultSidebarItemsGenerator(args);
return reverseSidebarItems(sidebarItems);
},
},
],
],
};

Hideable sidebar

Using the enabled themeConfig.hideableSidebar option, you can make the entire sidebar hidden, allowing you to better focus your users on the content. This is especially useful when content consumption on medium screens (e.g. on tablets).

docusaurus.config.js
module.exports = {
themeConfig: {
hideableSidebar: true,
},
};

Passing custom props

To pass in custom props to a swizzled sidebar item, add the optional customProps object to any of the items:

{
type: 'doc',
id: 'doc1',
customProps: {
/* props */
}
}

Complex sidebars example

Real-world example from the Docusaurus site:

sidebars.js
// @ts-check
const sidebars = {
docs: [
'introduction',
{
type: 'category',
label: 'Getting Started',
collapsed: false,
items: [
'installation',
'configuration',
'playground',
'typescript-support',
],
},
{
type: 'category',
label: 'Guides',
items: [
'guides/creating-pages',
{
Docs: [
'guides/docs/introduction',
'guides/docs/create-doc',
'guides/docs/sidebar',
'guides/docs/versioning',
'guides/docs/markdown-features',
'guides/docs/multi-instance',
],
},
'blog',
{
type: 'category',
label: 'Markdown Features',
items: [
'guides/markdown-features/introduction',
'guides/markdown-features/react',
'guides/markdown-features/tabs',
'guides/markdown-features/code-blocks',
'guides/markdown-features/admonitions',
'guides/markdown-features/headings',
'guides/markdown-features/inline-toc',
'guides/markdown-features/assets',
'guides/markdown-features/plugins',
'guides/markdown-features/math-equations',
'guides/markdown-features/head-metadatas',
],
},
'styling-layout',
'static-assets',
'search',
'browser-support',
'deployment',
{
type: 'category',
label: 'Internationalization',
items: [
{
type: 'doc',
id: 'i18n/introduction',
label: 'Introduction',
},
{
type: 'doc',
id: 'i18n/tutorial',
label: 'Tutorial',
},
{
type: 'doc',
id: 'i18n/git',
label: 'Using Git',
},
{
type: 'doc',
id: 'i18n/crowdin',
label: 'Using Crowdin',
},
],
},
],
},
{
type: 'category',
label: 'Advanced Guides',
items: ['using-plugins', 'using-themes', 'presets'],
},
{
type: 'category',
label: 'Migrating from v1 to v2',
items: [
'migration/migration-overview',
'migration/migration-automated',
'migration/migration-manual',
'migration/migration-versioned-sites',
'migration/migration-translated-sites',
],
},
],
api: [
'cli',
'docusaurus-core',
'api/docusaurus.config.js',
'lifecycle-apis',
{
type: 'category',
label: 'Plugins',
items: [
'api/plugins/plugins-overview',
'api/plugins/plugin-content-docs',
'api/plugins/plugin-content-blog',
'api/plugins/plugin-content-pages',
'api/plugins/plugin-client-redirects',
'api/plugins/plugin-debug',
'api/plugins/plugin-google-analytics',
'api/plugins/plugin-google-gtag',
'api/plugins/plugin-ideal-image',
'api/plugins/plugin-pwa',
'api/plugins/plugin-sitemap',
],
},
{
type: 'category',
label: 'Themes',
items: [
'api/themes/themes-overview',
'api/themes/theme-configuration',
'api/themes/theme-classic',
'api/themes/theme-live-codeblock',
'api/themes/theme-search-algolia',
],
},
],
};
module.exports = sidebars;