close
  • English
  • Autogenerated navigation

    In Rspress, you can either declare nav and sidebar in the config file or generate them automatically from _nav.json and _meta.json. We recommend the latter because it keeps the config file concise, supports HMR, and still exposes everything under themeConfig.

    Tip

    Autogenerated navbar/sidebar only works when rspress.config.ts does not define nav or sidebar.

    Basic usage

    Rspress generates the navbar from _nav.json and the sidebar from _meta.json. The navbar-level _nav.json lives in the docs root, while sidebar-level _meta.json files live in subdirectories under the docs root. For example:

    docs
    _nav.json// navigation bar level
    guide
    _meta.json// sidebar level
    introduction.mdx
    advanced
    _meta.json// sidebar level
    plugin-development.md

    If your site uses i18n, place the navbar-level _nav.json in each language directory:

    docs
    en
    _nav.json// navigation bar level
    guide
    _meta.json// sidebar level
    introduction.mdx
    install.mdx
    advanced
    _meta.json// sidebar level
    plugin-development.md
    zh
    _nav.json// navigation bar level
    guide
    _meta.json// sidebar level
    introduction.mdx
    install.mdx
    advanced
    _meta.json// sidebar level
    plugin-development.md

    By default (only _nav.json exists at the root), Rspress generates a separate sidebar for each subdirectory. The sidebar switches automatically based on the currently active nav item. For example, clicking the "Guide" nav item shows the Guide sidebar, and clicking "API" shows the API sidebar:

    docs
    _nav.json
    guide
    _meta.json// sidebar for /guide
    ...
    api
    _meta.json// sidebar for /api
    ...

    If you want all pages to share a single global sidebar instead of switching by nav, you can add a _meta.json at the root level of the docs directory (alongside _nav.json).

    This approach works better for documentation sites with fewer nav items and a simpler structure. Since the sidebar stays the same regardless of which nav item is active, it is a good fit when you want to organize the whole site under one unified sidebar:

    docs
    _nav.json
    _meta.json// root-level _meta.json → global sidebar
    guide
    _meta.json
    ...
    api
    _meta.json
    ...

    When a root-level _meta.json exists, Rspress will generate a single sidebar (keyed by '/') for all pages, regardless of which nav item is active. The root _meta.json serves as the entry point for the entire sidebar tree, and you can typically organize subdirectories with section headers:

    docs/_meta.json
    [
      {
        "type": "dir-section-header",
        "name": "guide",
        "label": "Guide"
      },
      {
        "type": "dir-section-header",
        "name": "api",
        "label": "API"
      }
    ]

    JSON schema type hint

    To improve editing for _nav.json and _meta.json, Rspress provides two schema files for IDE hints: @rspress/core/meta-json-schema.json and @rspress/core/nav-json-schema.json.

    For example, in VSCode, you can add the following configuration in .vscode/settings.json:

    .vscode/settings.json
    {
      //...
      "json.schemas": [
        {
          "fileMatch": ["**/_meta.json"],
          "url": "./node_modules/@rspress/core/meta-json-schema.json"
          // or "url": "https://unpkg.com/@rspress/core@2.0.0/meta-json-schema.json"
        },
        {
          "fileMatch": ["**/_nav.json"],
          "url": "./node_modules/@rspress/core/nav-json-schema.json"
          // or "url": "https://unpkg.com/@rspress/core@2.0.0/nav-json-schema.json"
        }
      ]
      // ...
    }

    At the navbar level, _nav.json accepts an array with the same type as the default theme's nav config. For details, see nav config. For example:

    docs/_nav.json
    [
      {
        "text": "Guide",
        "link": "/guide/introduction",
        "activeMatch": "^/guide/"
      }
    ]

    At the sidebar level, _meta.json accepts an array whose items use the following types:

    export type FileSideMeta = {
      type: 'file';
      name: string;
      label?: string;
      tag?: string;
      overviewHeaders?: number[];
      context?: string;
    };
    
    export type DirSideMeta = {
      type: 'dir';
      name: string;
      label?: string;
      collapsible?: boolean;
      collapsed?: boolean;
      tag?: string;
      overviewHeaders?: number[];
      context?: string;
    };
    
    export type DirSectionHeaderSideMeta = Omit<DirSideMeta, 'type'> &
      Omit<SectionHeaderMeta, 'type'> & { type: 'dir-section-header' };
    
    export type DividerSideMeta = {
      type: 'divider';
      dashed?: boolean;
    };
    
    export type SectionHeaderMeta = {
      type: 'section-header';
      label: string;
      tag?: string;
    };
    
    export type CustomLinkMeta =
      | {
          // file link
          type: 'custom-link';
          label: string;
          tag?: string;
          overviewHeaders?: number[];
          context?: string;
          link: string;
        }
      | {
          // dir link
          type: 'custom-link';
          label: string;
          tag?: string;
          overviewHeaders?: number[];
          context?: string;
          link?: string;
          collapsible?: boolean;
          collapsed?: boolean;
          items: _CustomLinkMetaWithoutTypeField[];
        };
    
    export type SideMetaItem =
      | FileSideMeta
      | DirSideMeta
      | DirSectionHeaderSideMeta
      | DividerSideMeta
      | SectionHeaderMeta
      | CustomLinkMeta
      | string;

    file

    • When the item is a string, it represents a file. The string is the file name:
    ["introduction"]

    The file name may include a suffix or omit it. For example, introduction is resolved as introduction.mdx.

    • When the item is an object, it can describe a file, directory, or custom link.

    To describe a file, use the following type:

    export type FileSideMeta = {
      type: 'file';
      name: string;
      label?: string;
      tag?: string;
      overviewHeaders?: number[];
      context?: string;
    };

    Here, name is the file name with or without a suffix, and label is the file's display name in the sidebar. If label is omitted, Rspress uses the document's H1 title automatically. overviewHeaders controls which headings are shown on the file's overview page; it is optional and defaults to [2]. context adds a data-context attribute to the generated sidebar DOM node; it is optional and omitted by default. For example:

    {
      "type": "file",
      "name": "introduction",
      "label": "Introduction"
    }

    dir

    To describe a directory, use the following type:

    export type DirSideMeta = {
      type: 'dir';
      name: string;
      label?: string;
      collapsible?: boolean;
      collapsed?: boolean;
      tag?: string;
      overviewHeaders?: number[];
      context?: string;
    };

    Here, name is the directory name, label is the directory's display name in the sidebar, collapsible controls whether the directory can be collapsed, and collapsed controls whether it is collapsed by default. overviewHeaders controls which headings are shown on overview pages for files in this directory; it is optional and defaults to [2]. context adds a data-context attribute to the generated sidebar DOM node; it is optional and omitted by default. For example:

    {
      "type": "dir",
      "name": "advanced",
      "label": "Advanced",
      "collapsible": true,
      "collapsed": false
    }
    Tip

    To display a document when users click a sidebar directory, create an index.mdx file inside that directory. For example:

    docs
    basic
    guide
    index.mdx
    getting-started.mdx
    _meta.json
    _meta.json
    basic/_meta.json
    [{ "type": "dir", "name": "guide" }]
    basic/guide/_meta.json
    ["getting-started"]

    This sidebar contains only the getting-started document. When users click the Guide directory, Rspress displays the content of index.mdx.

    dir-section-header new

    When describing a directory, you can also use dir-section-header. It behaves like "type": "dir" but renders differently in the UI. It is often used at the first level, where the directory title appears as a section header at the same level as files inside the directory.

    Type:

    export type DirSectionHeaderSideMeta = Omit<DirSideMeta, 'type'> &
      Omit<SectionHeaderMeta, 'type'> & { type: 'dir-section-header' };
    {
      "type": "dir-section-header",
      "name": "advanced",
      "label": "Advanced",
      "collapsible": true,
      "collapsed": false
    }

    divider

    To describe a divider, use the following type:

    export type DividerSideMeta = {
      type: 'divider';
      dashed?: boolean;
    };

    When dashed is true, the divider is dashed. Otherwise, it is solid.

    section-header

    To describe a section header, use the following type:

    export type SectionHeaderMeta = {
      type: 'section-header';
      label: string;
      tag?: string;
    };

    Here, label is the section header's display name in the sidebar. For example:

    {
      "type": "section-header",
      "label": "Section Header"
    }

    Section headers make it easier to group documents and directories in the sidebar. You can combine them with divider to separate groups more clearly:

    [
      {
        "type": "section-header",
        "label": "Section 1"
      },
      "introduction",
      {
        "type": "divider"
      },
      {
        "type": "section-header",
        "label": "Section 2"
      },
      "advanced"
    ]

    To describe a custom link, use the following type:

    export type CustomLinkMeta =
      | {
          // file link
          type: 'custom-link';
          label: string;
          tag?: string;
          overviewHeaders?: number[];
          context?: string;
          link: string;
        }
      | {
          // dir link
          type: 'custom-link';
          label: string;
          tag?: string;
          overviewHeaders?: number[];
          context?: string;
          link?: string;
          collapsible?: boolean;
          collapsed?: boolean;
          items: _CustomLinkMetaWithoutTypeField[];
        };

    Here, link is the link target and label is the display name in the sidebar. For example:

    {
      "type": "custom-link",
      "link": "/my-link",
      "label": "My Link"
    }

    link supports external links, for example:

    {
      "type": "custom-link",
      "link": "https://github.com",
      "label": "GitHub"
    }

    You can also use items to create nested custom links, for example:

    {
      "type": "custom-link",
      "label": "My Link",
      "items": [
        {
          "type": "custom-link",
          "label": "Sub Link 1",
          "link": "/sub-link-1"
        },
        {
          "type": "custom-link",
          "label": "Sub Link 2",
          "link": "/sub-link-2"
        }
      ]
    }

    Complete example

    Here is a complete example using the three types above:

    [
      "install",
      {
        "type": "file",
        "name": "introduction",
        "label": "Introduction"
      },
      {
        "type": "dir",
        "name": "advanced",
        "label": "Advanced",
        "collapsible": true,
        "collapsed": false
      },
      {
        "type": "custom-link",
        "link": "/my-link",
        "label": "My Link"
      }
    ]

    No config usage

    In some directories, you can omit _meta.json and let Rspress generate the sidebar automatically. This works when the directory contains only documents, no subdirectories, and you do not need a custom document order. For example:

    docs
    _meta.json
    guide
    _meta.json
    basic
    introduction.mdx
    install.mdx
    plugin-development.md

    In the guide directory, configure _meta.json as follows:

    [
      {
        "type": "dir",
        "name": "basic",
        "label": "Basic",
        "collapsible": true,
        "collapsed": false
      }
    ]

    In the basic directory, you can omit _meta.json; Rspress then generates the sidebar automatically and sorts files alphabetically by file name. To customize the order, prefix file names with numbers:

    basic
    1-introduction.mdx
    2-install.mdx
    3-plugin-development.md

    Tag icons for sidebar and navbar

    You can add icons after titles in the sidebar or navbar through the tag config. The value of tag supports SVG tag strings or image URLs.

    _meta.json
    {
      "type": "file",
      "name": "introduction",
      "label": "Introduction",
      "tag": "<svg width=\"1em\" height=\"1em\" viewBox=\"0 0 32 32\"><path fill=\"currentColor\" d=\"M4 6h24v2H4zm0 18h24v2H4zm0-12h24v2H4zm0 6h24v2H4z\"/></svg>"
    }

    For detailed usage, see Tag Component.