Docusaurus supplies useful SEO foundations, including generated HTML and page metadata. The work left for a documentation team is to verify that the deployed pages contain the right answer, identify the right version and language, and expose consistent URLs to readers and crawlers.
These 15 Docusaurus SEO checks focus on that release workflow. They cover documentation pages, their navigation and supporting metadata, with examples based on the official 3.10.2 documentation. Check your installed core, preset and plugin versions before copying version-specific options.
The examples are illustrative configurations and expected outputs, not results from a tested deployment. Merge relevant settings into your existing site; do not replace working presets, rename established routes or hide supported documentation simply to match the examples.
Verify the route and the generated answer
Choose a small but meaningful sample before editing: one normal guide, one reference page, one older supported version, and one real translation if your site has them. Include a deliberately nonexistent path for the hosting check later. Mark unavailable page types as not applicable.
For the examples below, the site lives under https://example.com/help/, the docs plugin uses docs as its route prefix, and the guide's slug is /webhook-retries. The intended public guide is therefore https://example.com/help/docs/webhook-retries/.
1. Separate the origin, deployment base and docs prefix
Inspect url and baseUrl in your site configuration, then the docs plugin's routeBasePath. They describe different pieces of the public address. A copied preview domain or a repeated /docs/ prefix can produce incorrect metadata even when a page loads locally.
For this illustrative subpath deployment, merge these fields into the existing configuration:
// Relevant fields in docusaurus.config.js
export default {
url: 'https://example.com',
baseUrl: '/help/',
trailingSlash: true,
};
The example retains the docs plugin's default routeBasePath: 'docs'. If your site uses docs-only mode with a different prefix, map that actual configuration instead. Do not add /help/ or /docs/ again to every slug.
The site configuration reference explains the origin, base path and trailing-slash output. Compare a generated link, its canonical and its final public response. They should agree on the intended host and path. A host that redirects every generated trailing-slash URL to the opposite form needs a deliberate policy decision, not a blind string replacement.
2. Find the useful answer in generated HTML
Run your project's production build and inspect the generated file for the sample route. Then capture the public response separately. For example:
curl -sS -D guide-headers.txt \
https://example.com/help/docs/webhook-retries/ \
-o guide.html
Inspect guide.html for a distinctive sentence from the answer, the main heading and ordinary links to related documentation. A title, navigation shell and loading message do not prove the actual instructions are present.
Docusaurus generates HTML before hydration, but custom content inside BrowserOnly, or data loaded only after a browser effect, can still leave an incomplete initial answer. Keep essential explanations available in generated content and reserve browser-dependent components for the interactions that require them.
Compare direct navigation with navigation from another docs page. Investigate differences in the affected component or data-loading path. Our SSR and CSR guide explains the broader distinction. A successful build establishes neither complete public delivery nor Google indexing.
Make page metadata describe the right document
3. Check the title, visible heading and sidebar label
A short sidebar label helps navigation, while a page title needs enough context to identify the answer. Inspect each output instead of assuming that all three should contain exactly the same text.
This original example belongs in a Markdown document processed by the docs plugin:
---
title: Configure webhook retries
description: Learn how to configure webhook retry limits, handle failed deliveries, and verify retry behavior for your integration.
slug: /webhook-retries
sidebar_label: Webhook retries
---
# Configure webhook retries
Set the retry limit before enabling the webhook integration.
The docs front-matter reference defines these fields. The slug is relative to the docs route structure; it does not require copying the /docs/ prefix into the field. With the previous configuration, the guide remains under /help/docs/webhook-retries/.
Check the emitted <title> for the intended topic and any theme-added site suffix. Check the visible heading and sidebar separately. An explicit Markdown heading can differ from the front-matter title; hide_title affects the automatically supplied title, not an explicit Markdown heading.
Use a concise, accurate title. Do not promise a particular Google title-link display from a character count or repeat the product name several times through overlapping suffix rules.
4. Replace an unhelpful description fallback
Without a suitable explicit description, Docusaurus can derive one from the first meaningful content line. That may produce a reasonable summary, or it may expose an introductory warning, navigation instruction or fragment of formatted text.
Inspect the actual meta description on a guide and a reference page. If it does not explain the page's task, add a specific description in front matter, as in the example above. Rebuild and verify the new output. Check that another custom head component has not retained conflicting metadata.
The head-metadata guide explains the fallback and how descriptions can also be reused in documentation cards. A misleading field can therefore affect both a sharing surface and navigation within your own site.
Write for the reader's decision: what can this document help them accomplish, and under what relevant product or version context? Google may generate a snippet from other page content, so a saved description is not a guaranteed search-result excerpt.
5. Verify the canonical that the page actually publishes
The Docusaurus SEO guide describes its automatically supplied metadata, including canonicals. Before adding a custom one, inspect the generated head and identify its existing owner.
For the example guide, the expected preferred address is:
<link rel="canonical" href="https://example.com/help/docs/webhook-retries/">
Check the real host, /help/ deployment base, docs prefix and trailing-slash policy. Look for preview domains, duplicated prefixes and overrides left in custom MDX head content or a modified layout. Compare generated HTML with the public response; a correct source file can still be deployed under the wrong host configuration.
Use a custom canonical only for a real consolidation decision, with one consistent intended destination. It does not make an unrelated page equivalent or force Google to choose it. Our canonical-tag guide covers that broader policy. Versioned documentation needs the separate decision in the next check.
Treat versions, languages and visibility separately
6. Decide which documentation versions should appear in search
In Docusaurus terminology, current identifies the source in docs/; latest identifies the version preferred by navigation. They are not automatically the same release. Inspect versions.json, the docs options and the actual public version selector before editing a file.
For example, a versioned site with fictional product releases 2.0 and 1.0 could follow this default arrangement:
| Source | Meaning | Illustrative public path |
|---|---|---|
docs/webhook-retries.md |
Current work, often labeled Next | /help/docs/next/webhook-retries/ |
versioned_docs/version-2.0/webhook-retries.md |
Latest frozen release | /help/docs/webhook-retries/ |
versioned_docs/version-1.0/webhook-retries.md |
Older release | /help/docs/1.0/webhook-retries/ |
These are product-documentation versions, not Docusaurus package versions. The versioning guide explains the defaults and overrides. In this arrangement, editing docs/ changes the Next page rather than the unversioned public guide used in the earlier examples.
Make a decision for each release instead of canonicalizing every old page to the latest one:
| Situation | Decision to investigate |
|---|---|
| An older supported release has different working instructions | Keep a useful, clearly identified version page; assess it on its own merits |
| Two URLs contain genuinely duplicate or very similar material | Consider an appropriate canonical consolidation and consistent links |
| A public work-in-progress version should stay out of search | Use the supported version-level indexing setting and verify output |
| Content must be confidential | Keep it behind access control or out of the public deployment |
For an already published WIP current version that should not appear in search, the relevant preset fragment can be:
// Merge into the existing classic preset options.
export default {
presets: [
['classic', {
docs: {
versions: {
current: {noIndex: true},
},
},
}],
],
};
Do not apply that example when current is your intended searchable release. Confirm which version the option targets, rebuild, and inspect a page from that version plus one intended searchable release. Avoid automatically stripping a version segment to generate a canonical: the destination may have different instructions or may not exist.
7. Verify real language equivalents and their alternates
Check the configured locales against files that were actually translated and deployed. For each sample document, open the alternate URL and read enough to establish that it is the equivalent answer in the stated language.
For a single-domain site, a French counterpart might be /help/fr/docs/webhook-retries/. A build targeting one locale for a separate domain can use a different path arrangement. The i18n tutorial explains that deployment distinction; do not add /fr/ manually to every URL without checking the build mode.
Inspect the actual hreflang links and language declaration. Docusaurus supplies alternate metadata for configured internationalization, but configuration alone does not prove that every destination is a complete translation. Check the return annotations, the page's own language entry and accessible equivalent destinations, following Google's localized-page guidance.
A translated homepage is not a substitute for a missing translated guide. Record a missing translation as missing. Avoid pointing every language's canonical to English simply because English is the default language.
8. Distinguish drafts, unlisted pages and crawl restrictions
Inspect three layers: site-wide noIndex, version-level policy, and individual page metadata. Then inspect the public response headers for a host-added X-Robots-Tag. A correctly configured source page can still inherit an unintended restriction.
For docs front matter, draft: true keeps the document out of production builds. unlisted: true makes it available by direct public URL while hiding it from normal production discovery and supplying noindex metadata. Neither is a substitute for authentication when information must remain private.
If a guide should appear in search but is missing, check these fields and the build's included versions before adding more links. If a public page should be excluded, verify the real robots metadata; merely removing its sitemap entry does not issue a noindex directive.
Finally, inspect the served robots.txt. It controls crawling, not confidentiality or canonical selection. Blocking crawling can prevent Google from reading a page's noindex instruction. Google's robots.txt explanation makes this distinction explicit.
Check discovery paths instead of trusting a page count
9. Compare the production sitemap with the intended page set
The sitemap plugin is included with preset-classic; do not install another copy without checking the existing setup. It operates on production build output, so a missing development-server sitemap is not proof of a broken release.
For the running example, fetch the real deployed file under the base path:
curl -sS -D sitemap-headers.txt \
https://example.com/help/sitemap.xml \
-o sitemap.xml
If you configured another filename, use that path. Confirm that the body is XML rather than an HTML fallback. If it is a sitemap index, follow its child files before comparing page URLs.
Prepare the intended searchable URL set from the actual deployed versions and translations. Compare it with the sitemap in both directions: missing eligible guides and unexpected entries. A matching count can hide one missing guide and one unwanted URL.
Check a searchable release page, an intentionally excluded WIP page and a real translation. The sitemap plugin reference describes ignorePatterns, custom filenames and output behavior. Global noIndex: true prevents sitemap generation, and pages with noindex metadata are filtered. An ignore pattern only removes an entry; it does not make the page non-indexable or private.
Account for the deployment base when reviewing patterns. Preserve valid versions rather than excluding every URL containing a number. Check modification dates against actual content history if you enable them. Screpy's XML sitemap guide explains the general discovery rules; submission still does not guarantee indexing.
10. Follow links through the correct version and plugin instance
Use relative Markdown file links when the target belongs to the same content plugin instance. If delivery-limits.md exists beside your source document, this example lets Docusaurus resolve its published URL:
[Review delivery limits](./delivery-limits.md)
The Markdown links guide explains how file references can follow slug changes and versioned documentation. A relative URL without a file extension is a different operation: the browser resolves it from the public URL, which may behave differently after trailing-slash changes.
File-reference resolution does not cross content plugin instances. A blog-to-docs link or a link between separate docs instances needs the appropriate URL approach. Open representative links from an older version and a translation; check that they do not silently send readers to another release or language.
For current Docusaurus versions, broken Markdown-link behavior is configured through this fragment:
// Merge into the existing site configuration.
export default {
markdown: {
hooks: {
onBrokenMarkdownLinks: 'throw',
},
},
};
The old top-level onBrokenMarkdownLinks option was deprecated in 3.9. Use the path supported by your installed version and run a production build. Treat reported failures as issues to resolve, not a reason to change all checks to ignore. A passing build is not a complete audit of external URLs or hosting responses.
Also follow the sidebar, category pages and next/previous links. Important guides need useful paths from the existing site, not merely a sitemap entry or a search overlay.
11. Preserve useful headings and stable fragment links
Scan a guide's rendered outline. Do the headings describe the steps and questions, or does a custom component hide the useful labels inside non-semantic containers? Check the real HTML rather than the apparent font size.
For headings referenced from other guides or translations, consider an explicit stable ID:
## Retry limits {#retry-limits}
Without an explicit ID, translating or renaming a heading can change its generated fragment. Verify that a link ending in #retry-limits still reaches the intended section in each relevant version and language.
Retain semantic tables, code and lists where they help explain the task. Do not impose a fixed heading count or depth to satisfy an SEO formula. The practical outcome is a document whose outline and shared links continue to work.
Inspect image and structured-data output
12. Open the actual image URLs and read their alternatives
A diagram that works on localhost can fail under a deployment subpath. Check an inline image, a custom React image and the page's declared social image separately.
For the example site, a file at static/img/retry-flow.png is served under /help/img/retry-flow.png. A literal JSX image source such as src="/img/retry-flow.png" instead points to the origin root. The static-assets guide describes supported imports and useBaseUrl for JSX; Markdown asset references are processed differently. Do not assume a literal React attribute receives the same rewriting as Markdown syntax.
Inspect the final src or declared social image URL, fetch it and confirm that it returns the intended image rather than HTML. Check dimensions, clarity and actual file weight. A page's image front-matter field describes preview metadata; it does not replace meaningful inline content or prove the image can be fetched publicly.
Read the actual alt attribute in context. Explain the information an informative image contributes, and keep essential instructions available as text. Decorative images need an appropriate empty alternative. Avoid keyword lists or alt text copied from an unrelated page.
Not every document needs an image. Add one when it explains a workflow, demonstrates a real interface or helps a reader understand something the prose cannot show as clearly.
13. Match structured data to the actual documentation page
Inspect both JSON-LD scripts and any microdata before deciding that structured data is missing. A site can use more than one syntax, and a JSON-LD-only search will overlook markup supplied another way.
For documentation, start with the real page identity and hierarchy. Check the following evidence:
| Output | What to compare |
|---|---|
| Page URL and name | The intended public guide and its actual title |
| Breadcrumb trail | A useful visitor path with correct labels and destinations |
| Any author or date fields | Real credited authorship and substantive history |
| Any image field | The correct, publicly accessible image |
| Duplicate markup | Whether separate components describe conflicting page facts |
Google's breadcrumb guidance focuses on useful navigation hierarchy. It does not require copying every URL directory into the breadcrumb trail. Validate supported output with the appropriate tools, then compare it with visible facts; valid syntax alone is insufficient.
Do not assume Docusaurus blog metadata proves that every docs page has equivalent Article markup. Inspect the actual docs template and its configuration. Adding a sitewide object with the same article title, publication date or author to every guide creates inaccurate data. A valid markup result also does not guarantee a rich result.
Test the host and the mobile reading experience
14. Check real HTTP responses, not just the visible screen
Test a valid deep documentation URL directly, then a deliberately nonexistent URL. A static host can serve the same application shell for both while returning 200 for a missing page. A visible “not found” message does not repair an incorrect HTTP status.
Capture the missing-route response separately:
curl -sS -D missing-headers.txt \
https://example.com/help/docs/this-page-does-not-exist/ \
-o missing.html
These curl examples deliberately do not follow redirects automatically. Inspect any redirect and its destination, then fetch the intended final URL. Require the real document on a valid deep link and a meaningful not-found response for an invalid one. Google's JavaScript SEO guidance explains why status codes and soft 404s matter.
Check established URLs after a rename or a release-path change. If an equivalent replacement exists, configure the intended redirect using your host's supported mechanism and update internal links. Do not redirect every removed guide to the documentation homepage. Retain useful older instructions at their own URLs when that is the correct product-support decision.
Save the observed response, destination and content with the release identifier. A local build/ file cannot establish which deployment or cached response the public host is currently serving.
15. Check whether a reader can use the docs on mobile
Open a normal guide and a heavy reference page on a narrow screen. Test the sidebar, version and language selectors, search, code-copy controls and any interactive examples. Look for overlays covering the answer, wide tables escaping the layout and content shifting while images load.
Check performance on those actual templates rather than only the homepage. Static generation does not eliminate image, JavaScript, font or third-party costs. Investigate a concrete issue before changing a bundling setting or removing a component that readers need.
PageSpeed Insights distinguishes lab diagnostics from real-user field data. Record whether field evidence concerns the exact page or the origin, as well as the device, date and conditions. A low-traffic guide may have no available field data; that is an unavailable result, not a pass.
After a focused fix, repeat comparable checks and confirm that essential interactions still work. A better lab score does not by itself establish a ranking gain or prove that every documentation template improved.
Keep evidence for the documentation release
Use one record per representative URL, with its version and language attached. Copy this worksheet and replace the placeholders with observations:
Release/build identifier: [actual release]
Checked at: [date, time and time zone]
Installed Docusaurus/core/preset/plugin versions: [actual versions]
Document source: [file and plugin instance]
Documentation version and locale: [actual values]
Expected public URL: [canonical destination]
Generated body and head: [observed result / unresolved difference]
Public response and final URL: [status, redirects, content]
Visibility policy and directives: [intended versus observed]
Sitemap inclusion: [present / intentionally absent / unexpectedly missing]
Navigation and fragment checks: [actual links followed]
Media, schema and mobile findings: [specific issues / not applicable]
Owner and next action: [smallest necessary correction]
For a larger release, extend the sample across templates, versions and locales, then reconcile the full expected URL inventory where a sample cannot establish coverage. Keep unknown observations marked as unknown.
When all relevant outputs agree, record the release as verified for those checks. Track Google's discovery and indexing separately: a published page, a sitemap entry and an accepted Request indexing submission are different states. None proves a ranking outcome.
Revisit the affected checks after a Docusaurus upgrade, a new documentation version, a locale deployment change, a theme override or a hosting migration. That gives the team a repeatable release record without turning every update into a new sitewide SEO project.