---
slug: /sidebar/autogenerated
---

# Autogenerated

```mdx-code-block
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
```

Docusaurus can **create a sidebar automatically** from your **filesystem structure**: each folder creates a sidebar category, and each file creates a doc link.

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

Docusaurus can generate a full sidebar from your docs folder:

```js title="sidebars.js"
module.exports = {
  myAutogeneratedSidebar: [
    // highlight-start
    {
      type: 'autogenerated',
      dirName: '.', // '.' means the current docs folder
    },
    // highlight-end
  ],
};
```

An `autogenerated` item is converted by Docusaurus to a **sidebar slice** (also discussed in [category shorthands](items.mdx#category-shorthand)): a list of items of type `doc` or `category`, so you can splice **multiple `autogenerated` items** from multiple directories, interleaving them with regular sidebar items, in one sidebar level.

<details>
<summary>A real-world example</summary>

Consider this file structure:

```bash
docs
├── api
│   ├── product1-api
│   │   └── api.md
│   └── product2-api
│       ├── basic-api.md
│       └── pro-api.md
├── intro.md
└── tutorials
    ├── advanced
    │   ├── advanced1.md
    │   ├── advanced2.md
    │   └── read-more
    │       ├── resource1.md
    │       └── resource2.md
    ├── easy
    │   ├── easy1.md
    │   └── easy2.md
    ├── tutorial-end.md
    ├── tutorial-intro.md
    └── tutorial-medium.md
```

And assume every doc's ID is just its file name. If you define an autogenerated sidebar like this:

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

It would be resolved as:

```js title="sidebars.js"
module.exports = {
  mySidebar: [
    'intro',
    {
      type: 'category',
      label: 'Tutorials',
      items: [
        'tutorial-intro',
        // highlight-start
        // Two files in docs/tutorials/easy
        'easy1',
        'easy2',
        // highlight-end
        'tutorial-medium',
        // highlight-start
        // Two files and a folder in docs/tutorials/hard
        'advanced1',
        'advanced2',
        {
          type: 'category',
          label: 'read-more',
          items: ['resource1', 'resource2'],
        },
        // highlight-end
        'tutorial-end',
      ],
    },
    // highlight-start
    // Two folders in docs/api
    {
      type: 'category',
      label: 'product1-api',
      items: ['api'],
    },
    {
      type: 'category',
      label: 'product2-api',
      items: ['basic-api', 'pro-api'],
    },
    // highlight-end
    {
      type: 'category',
      label: 'Community',
      items: ['team', 'chat'],
    },
  ],
};
```

Note how the autogenerate source directories themselves don't become categories: only the items they contain do. This is what we mean by "sidebar slice".

</details>

## Category index convention {#category-index-convention}

Docusaurus can automatically link a category to its index document.

A category index document is a document following one of those filename conventions:

- Named as `index` (case-insensitive): `docs/Guides/index.md`
- Named as `README` (case-insensitive): `docs/Guides/README.mdx`
- Same name as parent folder: `docs/Guides/Guides.md`

This is equivalent to using a category with a [doc link](items.mdx#category-doc-link):

```js title="sidebars.js"
module.exports = {
  docs: [
    // highlight-start
    {
      type: 'category',
      label: 'Guides',
      link: {type: 'doc', id: 'Guides/index'},
      items: [],
    },
    // highlight-end
  ],
};
```

:::tip

Naming your introductory document `README.md` makes it show up when browsing the folder using the GitHub interface, while using `index.md` makes the behavior more in line with how HTML files are served.

:::

:::tip

If a folder only has one index page, it will be turned into a link instead of a category. This is useful for **asset collocation**:

```
some-doc
├── index.md
├── img1.png
└── img2.png
```

:::

<details>

<summary>Customizing category index matching</summary>

It is possible to opt out any of the category index conventions, or define even more conventions. You can inject your own `isCategoryIndex` matcher through the [`sidebarItemsGenerator`](#customize-the-sidebar-items-generator) callback. For example, you can also pick `intro` as another file name eligible for automatically becoming the category index.

```js title="docusaurus.config.js"
module.exports = {
  plugins: [
    [
      '@docusaurus/plugin-content-docs',
      {
        async sidebarItemsGenerator({
          ...args,
          isCategoryIndex: defaultCategoryIndexMatcher, // The default matcher implementation, given below
          defaultSidebarItemsGenerator,
        }) {
          return defaultSidebarItemsGenerator({
            ...args,
            // highlight-start
            isCategoryIndex(doc) {
              return (
                // Also pick intro.md in addition to the default ones
                doc.fileName.toLowerCase() === 'intro' ||
                defaultCategoryIndexMatcher(doc)
              );
            },
            // highlight-end
          });
        },
      },
    ],
  ],
};
```

Or choose to not have any category index convention.

```js title="docusaurus.config.js"
module.exports = {
  plugins: [
    [
      '@docusaurus/plugin-content-docs',
      {
        async sidebarItemsGenerator({
          ...args,
          isCategoryIndex: defaultCategoryIndexMatcher, // The default matcher implementation, given below
          defaultSidebarItemsGenerator,
        }) {
          return defaultSidebarItemsGenerator({
            ...args,
            // highlight-start
            isCategoryIndex() {
              // No doc will be automatically picked as category index
              return false;
            },
            // highlight-end
          });
        },
      },
    ],
  ],
};
```

The `isCategoryIndex` matcher will be provided with three fields:

- `fileName`, the file's name without extension and with casing preserved
- `directories`, the list of directory names _from the lowest level to the highest level_, relative to the docs root directory
- `extension`, the file's extension, with a leading dot.

For example, for a doc file at `guides/sidebar/autogenerated.md`, the props the matcher receives are

```js
const props = {
  fileName: 'autogenerated',
  directories: ['sidebar', 'guides'],
  extension: '.md',
};
```

The default implementation is:

```js
function isCategoryIndex({fileName, directories}) {
  const eligibleDocIndexNames = [
    'index',
    'readme',
    directories[0].toLowerCase(),
  ];
  return eligibleDocIndexNames.includes(fileName.toLowerCase());
}
```

</details>

## Autogenerated sidebar metadata {#autogenerated-sidebar-metadata}

For handwritten sidebar definitions, you would provide metadata to sidebar items through `sidebars.js`; for autogenerated, Docusaurus would read them from the item's respective file. In addition, you may want to adjust the relative position of each item because, by default, items within a sidebar slice will be generated in **alphabetical order** (using file and folder names).

### Doc item metadata {#doc-item-metadata}

The `label`, `className`, and `customProps` attributes are declared in front matter as `sidebar_label`, `sidebar_class_name`, and `sidebar_custom_props`, respectively. Position can be specified in the same way, via `sidebar_position` front matter.

```md title="docs/tutorials/tutorial-easy.md"
---
# highlight-start
sidebar_position: 2
sidebar_label: Easy
sidebar_class_name: green
# highlight-end
---

# Easy Tutorial

This is the easy tutorial!
```

### Category item metadata {#category-item-metadata}

Add a `_category_.json` or `_category_.yml` file in the respective folder. You can specify any category metadata and also the `position` metadata. `label`, `className`, `position`, and `customProps` will default to the respective values of the category's linked doc, if there is one.

<Tabs>
<TabItem value="JSON">

```json title="docs/tutorials/_category_.json"
{
  "position": 2.5,
  "label": "Tutorial",
  "collapsible": true,
  "collapsed": false,
  "className": "red",
  "link": {
    "type": "generated-index",
    "title": "Tutorial overview"
  },
  "customProps": {
    "description": "This description can be used in the swizzled DocCard"
  }
}
```

</TabItem>
<TabItem value="YAML">

```yml title="docs/tutorials/_category_.yml"
position: 2.5 # float position is supported
label: 'Tutorial'
collapsible: true # make the category collapsible
collapsed: false # keep the category open by default
className: red
link:
  type: generated-index
  title: Tutorial overview
customProps:
  description: This description can be used in the swizzled DocCard
```

</TabItem>
</Tabs>

:::info

If the `link` is explicitly specified, Docusaurus will not apply any [default conventions](items.mdx#category-index-convention).

The doc links can be specified relatively, e.g. if the category is generated with the `guides` directory, `"link": {"type": "doc", "id": "intro"}` will be resolved to the ID `guides/intro`, only falling back to `intro` if a doc with the former ID doesn't exist.

You can also use `link: null` to opt out of default conventions and not generate any category index page.

:::

:::info

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

:::

## Using number prefixes {#using-number-prefixes}

A simple way to order an autogenerated sidebar is to prefix docs and folders by number prefixes, which also makes them appear in the file system in the same order when sorted by file name:

```bash
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.

:::warning

**Prefer using [additional metadata](#autogenerated-sidebar-metadata)**.

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

```diff title="docs/02-Tutorial Easy/01-First Part.md"
- Check the [Tutorial End](../04-End.mdx);
+ Check the [Tutorial End](../05-End.mdx);
```

:::

## Customize the sidebar items generator {#customize-the-sidebar-items-generator}

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

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

:::tip

**Re-use and enhance the default generator** instead of writing a generator from scratch: [the default generator we provide](https://github.com/facebook/docusaurus/blob/main/packages/docusaurus-plugin-content-docs/src/sidebars/generator.ts) is 250 lines long.

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

```js title="docusaurus.config.js"
// highlight-start
// 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;
}
// highlight-end

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

:::
