Routing
Docusaurus' routing system follows single-page application conventions: one route, one component. In this section, we will begin by talking about routing within the three content plugins (docs, blog, and pages), and then go beyond to talk about the underlying routing system.
Routing in content pluginsβ
Every content plugin provides a routeBasePath
option. It defines where the plugins append their routes to. By default, the docs plugin puts its routes under /docs
; the blog plugin, /blog
; and the pages plugin, /
. You can think about the route structure like this:
Any route will be matched against this nested route config until a good match is found. For example, when given a route /docs/configuration
, Docusaurus first enters the /docs
branch, and then searches among the subroutes created by the docs plugin.
Changing routeBasePath
can effectively alter your site's route structure. For example, in Docs-only mode, we mentioned that configuring routeBasePath: '/'
for docs means that all routes that the docs plugin create would not have the /docs
prefix, yet it doesn't prevent you from having more subroutes like /blog
created by other plugins.
Next, let's look at how the three plugins structure their own "boxes of subroutes".
Pages routingβ
Pages routing are straightforward: the file paths directly map to URLs, without any other way to customize. See the pages docs for more information.
The component used for Markdown pages is @theme/MDXPage
. React pages are directly used as the route's component.
Blog routingβ
The blog creates the following routes:
- Posts list pages:
/
,/page/2
,/page/3
...- The component is
@theme/BlogListPage
.
- The component is
- Post pages:
/2021/11/21/algolia-docsearch-migration
,/2021/05/12/announcing-docusaurus-two-beta
...- Generated from each Markdown post.
- The routes are fully customizable through the
slug
front matter. - The component is
@theme/BlogPostPage
.
- Tags list page:
/tags
- The route is customizable through the
tagsBasePath
option. - The component is
@theme/BlogTagsListPage
.
- The route is customizable through the
- Tag pages:
/tags/adoption
,/tags/beta
...- Generated through the tags defined in each post's front matter.
- The routes always have base defined in
tagsBasePath
, but the subroutes are customizable through the tag'spermalink
field. - The component is
@theme/BlogTagsPostsPage
.
- Archive page:
/archive
- The route is customizable through the
archiveBasePath
option. - The component is
@theme/BlogArchivePage
.
- The route is customizable through the
Docs routingβ
The docs is the only plugin that creates nested routes. At the top, it registers version paths: /
, /next
, /2.0.0-beta.13
... which provide the version context, including the layout and sidebar. This ensures that when switching between individual docs, the sidebar's state is preserved, and that you can switch between versions through the navbar dropdown while staying on the same doc. The component used is @theme/DocPage
.
The individual docs are rendered in the remaining space after the navbar, footer, sidebar, etc. have all been provided by the DocPage
component. For example, this page, /docs/3.0.0-rc.1/advanced/routing
, is generated from the file at ./versioned_docs/version-3.0.0-rc.1/advanced/routing.md
. The component used is @theme/DocItem
.
The doc's slug
front matter customizes the last part of the route, but the base route is always defined by the plugin's routeBasePath
and the version's path
.
File paths and URL pathsβ
Throughout the documentation, we always try to be unambiguous about whether we are talking about file paths or URL paths. Content plugins usually map file paths directly to URL paths, for example, ./docs/advanced/routing.md
will become /docs/advanced/routing
. However, with slug
, you can make URLs totally decoupled from the file structure.
When writing links in Markdown, you could either mean a file path, or a URL path, which Docusaurus would use several heuristics to determine.
- If the path has a
@site
prefix, it is always an asset file path. - If the path has an
http(s)://
prefix, it is always a URL path. - If the path doesn't have an extension, it is a URL path. For example, a link
[page](../plugins)
on a page with URL/docs/advanced/routing
will link to/docs/plugins
. Docusaurus will only detect broken links when building your site (when it knows the full route structure), but will make no assumptions about the existence of a file. It is exactly equivalent to writing<a href="../plugins">page</a>
in a JSX file. - If the path has an
.md(x)
extension, Docusaurus would try to resolve that Markdown file to a URL, and replace the file path with a URL path. - If the path has any other extension, Docusaurus would treat it as an asset and bundle it.
The following directory structure may help you visualize this file β URL mapping. Assume that there's no slug customization in any page.
A sample site structure
.
βββ blog # blog plugin has routeBasePath: '/blog'
β βββ 2019-05-28-first-blog-post.md # -> /blog/2019/05/28/first-blog-post
β βββ 2019-05-29-long-blog-post.md # -> /blog/2019/05/29/long-blog-post
β βββ 2021-08-01-mdx-blog-post.mdx # -> /blog/2021/08/01/mdx-blog-post
β βββ 2021-08-26-welcome
β βββ docusaurus-plushie-banner.jpeg
β βββ index.md # -> /blog/2021/08/26/welcome
βββ docs # docs plugin has routeBasePath: '/docs'; current version has base path '/'
β βββ intro.md # -> /docs/intro
β βββ tutorial-basics
β β βββ _category_.json
β β βββ congratulations.md # -> /docs/tutorial-basics/congratulations
β β βββ markdown-features.mdx # -> /docs/tutorial-basics/congratulations
β βββ tutorial-extras
β βββ _category_.json
β βββ manage-docs-versions.md # -> /docs/tutorial-extras/manage-docs-versions
β βββ translate-your-site.md # -> /docs/tutorial-extras/translate-your-site
βββ src
β βββ pages # pages plugin has routeBasePath: '/'
β βββ index.module.css
β βββ index.tsx # -> /
β βββ markdown-page.md # -> /markdown-page
βββ versioned_docs
βββ version-1.0.0 # version has base path '/1.0.0'
βββ intro.md # -> /docs/1.0.0/intro
βββ tutorial-basics
β βββ _category_.json
β βββ congratulations.md # -> /docs/1.0.0/tutorial-basics/congratulations
β βββ markdown-features.mdx # -> /docs/1.0.0/tutorial-basics/markdown-features
βββ tutorial-extras
βββ _category_.json
βββ manage-docs-versions.md # -> /docs/1.0.0/tutorial-extras/manage-docs-versions
βββ translate-your-site.md # -> /docs/1.0.0/tutorial-extras/translate-your-site
So much about content plugins. Let's take one step back and talk about how routing works in a Docusaurus app in general.
Routes become HTML filesβ
Because Docusaurus is a server-side rendering framework, all routes generated will be server-side rendered into static HTML files. If you are familiar with the behavior of HTTP servers like Apache2, you will understand how this is done: when the browser sends a request to the route /docs/advanced/routing
, the server interprets that as request for the HTML file /docs/advanced/routing/index.html
, and returns that.
The /docs/advanced/routing
route can correspond to either /docs/advanced/routing/index.html
or /docs/advanced/routing.html
. Some hosting providers differentiate between them using the presence of a trailing slash, and may or may not tolerate the other. Read more in the trailing slash guide.
For example, the build output of the directory above is (ignoring other assets and JS bundle):
Output of the above workspace
build
βββ 404.html # /404/
βββ blog
β βββ archive
β β βββ index.html # /blog/archive/
β βββ first-blog-post
β β βββ index.html # /blog/first-blog-post/
β βββ index.html # /blog/
β βββ long-blog-post
β β βββ index.html # /blog/long-blog-post/
β βββ mdx-blog-post
β β βββ index.html # /blog/mdx-blog-post/
β βββ tags
β β βββ docusaurus
β β β βββ index.html # /blog/tags/docusaurus/
β β βββ hola
β β β βββ index.html # /blog/tags/hola/
β β βββ index.html # /blog/tags/