web-meta-framework-docusaurus

Installation
SKILL.md

Docusaurus

Quick Guide: Docusaurus 3.x is a React-powered static site generator for documentation. Configure everything in docusaurus.config.js (ESM). Use @docusaurus/preset-classic for docs + blog + pages + sitemap in one preset. Sidebars can be fully autogenerated from filesystem structure using _category_.json and front matter sidebar_position. Customize theme components via swizzling (prefer --wrap over --eject). MDX is the default content format — use front matter for metadata, admonitions for callouts, and import React components directly in .mdx files. Version docs with docusaurus docs:version. Deploy the build/ output to any static host.


<critical_requirements>

CRITICAL: Before Using This Skill

All code must follow project conventions in CLAUDE.md

(You MUST use docusaurus.config.js (or .ts) as the single source of truth for all site configuration — never scatter config across multiple files)

(You MUST use @docusaurus/preset-classic unless you have a specific reason to configure plugins individually — the preset bundles docs, blog, pages, sitemap, and theme)

(You MUST prefer --wrap over --eject when swizzling — wrapping preserves upstream updates, ejecting creates a maintenance burden)

(You MUST use front matter sidebar_position and _category_.json for sidebar ordering in autogenerated sidebars — do not fight the filesystem-driven convention)

(You MUST NOT mix versioned and unversioned docs in the same plugin instance — use separate plugin instances for different doc sets)

</critical_requirements>


Auto-detection: Docusaurus, docusaurus.config.js, docusaurus.config.ts, @docusaurus/preset-classic, @docusaurus/core, sidebars.js, docs:version, docusaurus build, docusaurus start, docusaurus deploy, docusaurus swizzle, MDX, category.json, sidebar_position, @site, @theme, @theme-original, plugin-content-docs, plugin-content-blog

When to use:

  • Configuring docusaurus.config.js (site metadata, presets, plugins, theme, navbar, footer)
  • Setting up or modifying sidebar structure (autogenerated or manual)
  • Adding versioned documentation
  • Customizing theme components via swizzling
  • Writing MDX content with Docusaurus-specific features (admonitions, tabs, code blocks)
  • Creating custom pages with React components
  • Configuring the blog plugin
  • Setting up search (Algolia DocSearch or local)
  • Deploying Docusaurus to static hosting
  • Configuring i18n / localization

When NOT to use:

  • General React component patterns (Docusaurus uses React internally but this skill covers Docusaurus APIs, not React fundamentals)
  • CSS/styling approaches not specific to Docusaurus theming (general CSS patterns are a separate concern)
  • Git hooks, linting, or formatting setup (separate from documentation framework concerns)
  • Content that belongs in the docs themselves, not the site framework
  • VitePress — Vue-based, different config format and plugin system
  • Nextra — Next.js-based, uses _meta.json not _category_.json, different routing model
  • Starlight — Astro-based, uses astro.config.mjs and content collections, different architecture entirely

Examples

Other resources:

  • Quick Reference — CLI commands, front matter fields, config option tables

Philosophy

Docusaurus is an opinionated documentation framework that trades flexibility for convention. It makes strong decisions about routing (filesystem-based), content format (MDX), and structure (docs + blog + pages) so you can focus on writing content rather than building infrastructure.

Core principles:

  1. Convention over configuration — filesystem structure drives routing and sidebar generation; fight this and you fight the framework
  2. Preset-firstpreset-classic bundles the common plugin set; only decompose into individual plugins when you need multiple docs instances or unusual setups
  3. Content as data — front matter is the metadata layer; sidebar_position, slug, tags, custom_edit_url all live in the document, not in external config
  4. Swizzle, don't fork — customize theme components via the swizzle CLI; wrapping preserves upstream compatibility, ejecting creates a snapshot you must maintain
  5. Static outputdocusaurus build produces a static site; there is no server runtime, no SSR in production, no API routes

Core Patterns

Pattern 1: docusaurus.config.js Structure

The config file is the single entry point. It uses ESM (export default) and configures site metadata, presets (which bundle plugins + theme), and theme-level settings like navbar and footer.

// docusaurus.config.js — minimal production setup
export default {
  title: "My Docs",
  tagline: "Documentation for My Project",
  url: "https://docs.example.com",
  baseUrl: "/",
  onBrokenLinks: "throw",
  onBrokenMarkdownLinks: "throw",
  favicon: "img/favicon.ico",

  presets: [
    [
      "@docusaurus/preset-classic",
      {
        docs: {
          sidebarPath: "./sidebars.js",
          editUrl: "https://github.com/my-org/my-repo/edit/main/docs-site/",
          showLastUpdateTime: true,
        },
        blog: { showReadingTime: true },
        theme: { customCss: ["./src/css/custom.css"] },
      },
    ],
  ],

  themeConfig: {
    navbar: {
      title: "My Docs",
      items: [
        /* nav items */
      ],
    },
    footer: {
      style: "dark",
      links: [
        /* footer columns */
      ],
    },
    docs: { sidebar: { hideable: true, autoCollapseCategories: true } },
  },
};

Key gotcha: onBrokenLinks: 'throw' is essential for production — it fails the build on broken internal links rather than silently deploying dead links.

Full example: See examples/core.md for complete config with navbar, footer, and multi-instance docs setup.


Pattern 2: Sidebar Configuration

Docusaurus offers two sidebar strategies. Autogenerated sidebars derive structure from the filesystem and are the default recommendation. Manual sidebars give full control but require maintenance.

// sidebars.js — autogenerated (recommended)
export default {
  docs: [{ type: "autogenerated", dirName: "." }],
};

Control ordering and labels via front matter and _category_.json:

---
sidebar_position: 3
sidebar_label: Quick Start
---
// docs/guides/_category_.json
{
  "label": "Guides",
  "position": 2,
  "collapsible": true,
  "collapsed": false,
  "link": { "type": "generated-index", "title": "All Guides" }
}

Key gotcha: Without sidebar_position, items sort alphabetically by filename. Use number prefixes (01-intro.md) or front matter — but not both, as number prefixes are stripped from the URL slug.

Full example: See examples/core.md for manual sidebars, custom sidebar items generator, and multi-sidebar setups.


Pattern 3: Swizzling Theme Components

Swizzling lets you customize any theme component. Wrapping adds behavior around the original; ejecting gives you a full copy to modify.

# List all swizzlable components
npx docusaurus swizzle --list

# Wrap a component (SAFE — preserves upstream updates)
npx docusaurus swizzle @docusaurus/theme-classic Footer -- --wrap

# Eject a component (DANGEROUS — you own the snapshot)
npx docusaurus swizzle @docusaurus/theme-classic Footer -- --eject
// src/theme/Footer/index.js — wrapping example
import React from "react";
import Footer from "@theme-original/Footer";

export default function FooterWrapper(props) {
  return (
    <>
      <Footer {...props} />
      <div className="custom-banner">Custom content below footer</div>
    </>
  );
}

Key gotcha: The @theme-original/ import is critical in wrappers — it references the original component. Using @theme/ would create an infinite loop since your wrapper IS the @theme/Footer.

Full example: See examples/customization.md for swizzling safety levels, common swizzle targets, and CSS variable theming.


Pattern 4: MDX Content Features

Docusaurus uses MDX v3 — Markdown with embedded JSX. Key Docusaurus-specific features include admonitions, tabs, and code blocks with metadata.

---
title: My Document
description: SEO description for this page
sidebar_position: 1
tags: [getting-started, tutorial]
---

import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";

:::tip[Pro Tip]
Admonitions support `note`, `tip`, `info`, `warning`, `danger` types.
The bracket syntax `:::tip[Custom Title]` sets the title.
:::

<Tabs>
  <TabItem value="npm" label="npm" default>
    ```bash npm install my-package ```
  </TabItem>
  <TabItem value="yarn" label="yarn">
    ```bash yarn add my-package ```
  </TabItem>
</Tabs>

Key gotcha: MDX v3 is stricter than Markdown — unclosed HTML tags, bare { characters, and < comparisons in text will cause build errors. Escape them with \{ and \< or use code fences.

Full example: See examples/content.md for code block features, asset handling, and blog plugin configuration.


Pattern 5: Versioning

Docusaurus versions docs by snapshotting the entire docs/ directory. The current working copy is always current (next/unreleased). Cut a release version when shipping.

# Snapshot current docs as version 1.0.0
npx docusaurus docs:version 1.0.0

This creates versioned_docs/version-1.0.0/ and versioned_sidebars/version-1.0.0-sidebars.json. Configure version behavior in the docs plugin:

// In preset-classic docs options
docs: {
  lastVersion: 'current',
  versions: {
    current: { label: '2.0.0-beta', path: 'next', banner: 'unreleased' },
    '1.0.0': { label: '1.0.0', path: '1.0.0', banner: 'none' },
  },
  onlyIncludeVersions: ['current', '1.0.0'],
}

Key gotcha: Versioned docs are full copies, not diffs. Each version doubles the build time and output size. Use onlyIncludeVersions in development to speed up builds. Only version when you have actual API/feature differences — not for every release.

Full example: See examples/customization.md for version banner configuration and multi-version navigation.


<decision_framework>

Decision Framework

Sidebar Strategy

How should the sidebar be organized?
|-- Small docs site (< 30 pages)?
|   +-- Use autogenerated sidebar with sidebar_position front matter
|-- Large docs site with many sections?
|   |-- Sections map cleanly to directories? -> Autogenerated + _category_.json
|   +-- Need cross-directory grouping? -> Manual sidebar in sidebars.js
|-- Multiple independent doc sets (e.g., API + guides)?
|   +-- Use multiple docs plugin instances, each with its own sidebar
+-- Need to mix auto and manual?
    +-- Use autogenerated for most, with manual items for special entries

Swizzling Approach

Need to customize a theme component?
|-- Adding content around the component? -> Wrap (--wrap)
|-- Need to change the component's internal logic? -> Check safety level first
|   |-- Component marked "Safe"? -> Eject is acceptable
|   |-- Component marked "Unsafe"? -> Wrap if possible, eject only as last resort
|   +-- Component marked "Forbidden"? -> Do not swizzle — find another approach
+-- Just changing colors/spacing? -> Use CSS variables in custom.css (no swizzle needed)

Content Format

What kind of page am I creating?
|-- Documentation article? -> .md or .mdx file in docs/
|-- Blog post? -> .md or .mdx file in blog/
|-- Standalone page with custom layout?
|   |-- Mostly content? -> .mdx in src/pages/
|   +-- Mostly interactive/React? -> .tsx in src/pages/
+-- Need to embed React components in docs? -> Use .mdx with imports

</decision_framework>


<red_flags>

RED FLAGS

High Priority Issues:

  • Using onBrokenLinks: 'ignore' or 'log' in production — broken links should fail the build ('throw')
  • Ejecting theme components when wrapping would suffice — ejected components miss upstream bug fixes and feature additions
  • Using @theme/ComponentName import in a swizzle wrapper instead of @theme-original/ComponentName — creates an infinite import loop
  • Putting all sidebar config in sidebars.js manually when autogenerated would work — creates a maintenance burden that falls out of sync with actual docs

Medium Priority Issues:

  • Versioning every release instead of only when docs content actually changes — bloats build time and output size
  • Not setting onBrokenMarkdownLinks: 'warn' at minimum — silent broken links accumulate
  • Missing editUrl in docs plugin config — blocks "Edit this page" links that drive community contributions
  • Not using showLastUpdateTime: true — readers cannot tell how current a doc page is

Common Mistakes:

  • Bare { or < in MDX content causing build failures — escape with \{ and \< or wrap in code fences
  • Forgetting to restart the dev server after changing docusaurus.config.js — config changes are not hot-reloaded
  • Using .md extension with JSX when format: 'detect' is configured — in detect mode, only .mdx files support JSX (default mode processes both)
  • Creating _category_.json with wrong field names (name instead of label, order instead of position)
  • Importing from @docusaurus/ packages directly in MDX — use @theme/ or @site/ aliases instead

Gotchas & Edge Cases:

  • baseUrl must end with / — omitting the trailing slash breaks asset resolution
  • Static assets in static/ are served from root, not from baseUrl — use require() or useBaseUrl() for path-safe references
  • Blog authors are configured in blog/authors.yml, not in docusaurus.config.js
  • The slug front matter field overrides the URL path derived from the filename — useful for keeping clean URLs when renaming files
  • docs-only mode requires setting routeBasePath: '/' in the docs plugin AND blog: false in the preset
  • Custom pages in src/pages/ use the file path as the route — src/pages/support.tsx becomes /support
  • Tabs component state is not shared between instances by default — use groupId prop to sync tab selection across the page

</red_flags>


<critical_reminders>

CRITICAL REMINDERS

All code must follow project conventions in CLAUDE.md

(You MUST use docusaurus.config.js as the single source of truth for all site configuration)

(You MUST use @docusaurus/preset-classic unless you have a specific reason to configure plugins individually)

(You MUST prefer --wrap over --eject when swizzling — wrapping preserves upstream updates)

(You MUST use front matter sidebar_position and _category_.json for sidebar ordering — do not fight filesystem-driven conventions)

(You MUST NOT mix versioned and unversioned docs in the same plugin instance)

Failure to follow these rules will cause broken builds, unmaintainable theme overrides, and sidebar chaos.

</critical_reminders>

Related skills
Installs
2
GitHub Stars
6
First Seen
Apr 7, 2026