Docusaurus SEO: docs that rank and versions that do not fight
You run docs on Docusaurus and want them to rank. Here is the setup that avoids duplicate versions, fills the sitemap with the right URLs, and uses titles that win clicks. Each fix names the file to change and what good looks like.
By Théophile Louvart, founder of Porteur · Updated 14 September 2026 · Markdown
The shape of Docusaurus docs that rank
Make one page per task. The h1 is the question a user types. For example: “Connect SSO to Acme: Okta” at /docs/sso/okta.
- A single canonical URL for each task, never two
- A title that fits about 60 characters and leads with the task
- A meta description that earns the click in 120 to 155 characters
- Sidebars that link to the question pages, not only to categories
- Old versions that do not compete with current docs
Docusaurus gives you front matter for titles and descriptions, a sitemap plugin, docs versioning, i18n and built-in search. Use them with a simple rule: the current version is canonical, older versions are either noindexed or canonicalised to current.
Titles and meta from front matter
On each doc, set the page title and meta description in front matter. Keep the title short and specific. Put the task first, then the product or area.
---
title: Connect SSO to Acme: Okta
description: Set up SSO between Acme and Okta in five steps: create the app, map claims, test, and roll out to users.
slug: /docs/sso/okta
image: /img/og/sso-okta.png
keywords: [sso, okta, authentication]
---- title becomes the h1 and the HTML title
- description becomes the meta description
- slug fixes the URL if you move a file
- image is used for social cards if your theme reads it
- keywords are optional, some themes surface them
For tags Docusaurus does not set via front matter, add a Head block in MDX. Use it for rel=canonical and robots where needed.
import Head from '@docusaurus/Head';
<Head>
<link rel="canonical" href="https://yourproduct.com/docs/sso/okta" />
<meta name="robots" content="noindex" />
</Head>
# Connect SSO to Acme: OktaThe sitemap plugin: only list URLs you want indexed
Docusaurus ships a sitemap plugin. Configure it in docusaurus.config.js. Exclude old versions and utility pages. Then submit the sitemap in Search Console once.
// docusaurus.config.js
export default {
presets: [
[
'classic',
{
sitemap: {
changefreq: 'weekly',
priority: 0.6,
filename: 'sitemap.xml',
ignorePatterns: ['/docs/1.*/**', '/tags/**', '/search', '/404'],
},
},
],
],
};- Ignore old version paths like /docs/1.2/** if you keep them noindex
- Ignore tag and search routes if they exist on your theme
- Check the sitemap at /sitemap.xml after each release
- Use the Sitemaps report to see discovery and errors
If your site is on a subpath or behind a proxy, confirm the plugin outputs absolute URLs that match the public domain. If in doubt, check the platform’s current settings.
Versions that do not fight: the canonical rule
Versioned docs create duplicates by design. You want one winner per topic. The current version is canonical. Older versions either noindex themselves or point the canonical to the current page.
- If content is near identical, add rel=canonical on old versions to the current URL
- If content is materially different and still needed, keep old versions indexable only for versioned queries, else add noindex
- Exclude old versions from the sitemap in both cases
Pick a canonical URL pattern
Use clean unversioned paths for current docs, like /docs/sso/okta. Keep versioned paths under /docs/1.2/sso/okta.
Add canonical tags on old pages
In each old page or layout, add <Head><link rel="canonical" href="https://yourproduct.com/docs/sso/okta"/></Head>. Automate by reading the version from the route and stripping it.
Noindex long-tail versioned duplicates
If two old minors exist, keep the latest minor and set meta robots noindex on the others. This cuts crawl without hurting users who pinned a version.
Adjust internal links
Link to the current docs by default. Only link to old versions from a version picker or a clear note.
// Example: wrapper for old versions (theme swizzle or layout)
import Head from '@docusaurus/Head';
export default function OldVersionHead({currentUrl}) {
return (
<Head>
<link rel="canonical" href={currentUrl} />
<meta name="robots" content="noindex,follow" />
</Head>
);
}i18n without duplicate clutter
Docusaurus supports i18n. Each locale gets its own routes. Treat each locale as its own set of canonical pages. Do not leave placeholder translations indexable.
Define locales
Set i18n.defaultLocale and i18n.locales in docusaurus.config.js. Build once and check the URL paths for each language.
Set per-locale canonicals
Each locale’s page should self-canonical. Only point across locales if you truly merge pages. Keep the version canonical rule inside each locale.
Add hreflang
If your theme does not emit hreflang, add a Head block on pages or in a layout that prints links to alternates. Use the correct language-region codes. Check the platform’s current settings.
Avoid empty or auto-translated stubs
If a locale falls back to English, block the stub from indexing with meta robots noindex until it is translated.
import Head from '@docusaurus/Head';
<Head>
<link rel="alternate" href="https://yourproduct.com/docs/sso/okta" hreflang="en" />
<link rel="alternate" href="https://yourproduct.com/es/docs/sso/okta" hreflang="es" />
<link rel="alternate" href="https://yourproduct.com/docs/sso/okta" hreflang="x-default" />
</Head>Search that helps users, not index bloat
Docusaurus integrates site search inside the docs. This helps users complete tasks. It does not need to create indexable search pages, and usually does not. Keep it that way.
- If you add a results page under /search, set meta robots noindex on it
- Do not link to search results from your docs
- Make sure the search overlay loads fast and does not block content
You can add a WebSite SearchAction to your homepage to qualify for a sitelinks search box. This is optional but useful when the brand grows.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebSite",
"url": "https://yourproduct.com/",
"potentialAction": {
"@type": "SearchAction",
"target": "https://yourproduct.com/search?q={query}",
"query-input": "required name=query"
}
}
</script>llms.txt for documentation
AI crawlers read docs. Decide what they can use. Place an llms.txt at the root that sets your policy. In Docusaurus, add it to the static folder so it is served at /llms.txt.
Create /static/llms.txt
Keep it plain text. One rule per line. Point to a licence page if you allow use.
Tell what is allowed or disallowed
You can allow the whole site, allow only docs, or block everything except your homepage. Be explicit about derivatives if you care.
Publish and test
Build and deploy. Request https://yourproduct.com/llms.txt and confirm it loads. Update it when your docs move.
# llms.txt at https://yourproduct.com/llms.txt
User-Agent: *
Allow: /docs/
Disallow: /blog/drafts/
Derivatives: allowed
Commercialization: disallowed
Contact: [email protected]
Policy: https://yourproduct.com/docs/licenceWhat a fixed page looks like
Example: /docs/sso/okta in the current version. Title: “Connect SSO to Acme: Okta”. Description: “Set up SSO between Acme and Okta in five steps…”. It self-canonicals and appears in the sitemap. The old page at /docs/1.2/sso/okta has a canonical to the current URL, meta robots noindex, and is excluded from the sitemap. The Spanish page at /es/docs/sso/okta has a Spanish title, a Spanish description, self-canonical, and hreflang pairs with the English page.
Ship checklist for Docusaurus SEO
- Front matter has a clear task title and a real meta description on every doc
- Sitemap plugin is on, with ignorePatterns for old versions and utility pages
- Current docs use clean, unversioned URLs, and internal links point to them
- Old version pages add canonical to current or have meta robots noindex
- i18n pages self-canonical, and hreflang links connect alternates
- No indexable search results pages, and the overlay is fast
- llms.txt lives at /llms.txt with your chosen policy
- Generated index pages either have content or are noindexed
Questions
Swizzle the doc page layout or a wrapper and add a Head block that computes the current canonical from the route. If you cannot centralise it, add a small Head block to each old doc. Exclude those paths in the sitemap.
If the content is the same task with the same steps, canonicalise old versions to the current page. If the content is different enough that users still need it, keep the page available to users but set meta robots noindex. In both cases, do not list old versions in the sitemap.
If you have multiple locales, yes. It helps Google pair equivalents and show the right language. Emit hreflang on each localised page, including x-default on your default locale. If your theme already does this, you do not need to add it again.
Place llms.txt in the static folder so it is served from the site root at /llms.txt. Build and deploy, then fetch it in the browser to confirm. Update it when your docs path changes.
Title and description are the core. Add rel=canonical where versions exist. Add robots noindex on thin pages like search. Add Open Graph and Twitter tags if your theme does not set them and you share docs on social.
The built-in search is usually an overlay, not an indexable page. If you create a /search route that lists results, keep it noindex and out of the sitemap. Internal search helps users but does not add SEO value itself.
Sources
Check my site, free
Give your docs URL and we will read your site, the searches around it and the rivals on them in about thirty seconds, free, and show three findings you can ship now.
- Free check, no card
- Read-only, your own accounts
- Readable by your agent
Read next
- GuideSEO for documentation: one page per task, the task as the heading
- GuideCanonical tags: what they do and the mistakes that cost rankings
- GuideAlternate page with proper canonical tag: what Search Console means
- GuideThe Sitemaps report: what Success, Has errors and Couldn’t fetch mean
- GuideTitle tag length: what fits, what Google rewrites, and how to write one
- GuideMeta description length, with examples that earn the click
- GuideAstro SEO: fast by default, and the layout work that remains
- GuideGatsby SEO: static HTML, the Head API, and what to watch