Back to blog

Why Docusaurus Is the Wrong Default for Most Docs Teams

I’ve watched teams pick Docusaurus, feel great about it for about six weeks, and then spend the next year quietly suffering.

Docusaurus is not a bad tool. It is the wrong tool for most teams that choose it. And the gap between those two statements is where a lot of engineering hours go to die.

Before You Read Further

Answer these honestly. They’ll tell you whether this post is even for you.

  1. Who maintains the custom components and swizzled theme pieces when the person who built them leaves?
  2. Can your non-engineering contributors make edits without filing a ticket?
  3. When you need a reusable warning block, do you reach for a config option or write a React component?
  4. If you had to switch tools in two years, how painful would migrating your content be?
  5. Would a simpler tool handle 90% of your needs with 30% of the maintenance overhead?

If those questions made you uncomfortable, keep reading.

The Demo Trap

Here’s why Docusaurus keeps winning evaluations it shouldn’t win: it is exceptional in a demo.

Spin it up. It looks modern. It’s fast. The search works. The sidebar auto-generates. If you’ve got React chops, you’re customizing the theme inside of an hour. By end of day you’re showing stakeholders something that looks genuinely polished, and everyone nods.

That’s the trap.

What you just evaluated is how good Docusaurus is on day one. What you didn’t evaluate is what it feels like to maintain it when you’ve got 200 pages, three contributors who don’t know React, a quarterly release cycle, and a backlog of docs debt that keeps growing because nobody wants to touch the swizzled components.

Those are different questions. Docusaurus aces the first one and struggles badly with the second.

What Actually Goes Wrong

Your docs become a side software project

This is the big one. Docusaurus is built on a philosophy that docs can be — and maybe should be — a React application. That’s a reasonable idea for some teams. For most teams, it’s a slow-moving disaster.

It starts innocently. Someone drops a React component into an MDX file to render a nice callout box. Someone else swizzles the footer to add a feedback widget. A plugin gets added for something. Then another.

Three months later, your docs site has a src/components/ directory with seventeen custom components, a theme override that nobody fully understands, and a build pipeline that breaks whenever someone runs npm update. And the writers on your team — who just want to edit Markdown — have started filing tickets to ask engineers to make changes for them.

That’s not docs-as-code. That’s a frontend project that happens to contain documentation.

MDX is a trap disguised as a feature

MDX sounds great. Markdown plus React components! Maximum flexibility!

In practice it means your content is no longer portable. The moment you write:

<CustomCallout type="warning">
  Don't do this in production.
</CustomCallout>

…you’ve coupled that content to your Docusaurus setup. Move to a different tool later and you’re not migrating Markdown files — you’re migrating a content format that is specific to your current docs infrastructure.

And what does that migration actually look like? Every <CustomCallout>, <Tabs>, <TabItem>, and <CodeBlock> tag in your content becomes broken markup in any other renderer. You’re not doing a find-and-replace — you’re doing a content audit, a component inventory, and a rewrite pass across hundreds of files. Teams that thought they were building portable docs-as-code discover they built a Docusaurus-shaped content archive instead.

Docs-as-Code is supposed to mean the content outlives the tool. MDX quietly reverses that promise, and it happens gradually enough that most teams don’t notice until they’re already deep in it.

Writers become second-class citizens

Docusaurus is built by and for people who are comfortable with JavaScript and React. That’s fine if that describes everyone on your docs team.

It usually doesn’t.

Most teams have a mix: engineers, writers, DevRel, product managers, support folks who are subject-matter experts but not React developers. These people are often your most valuable docs contributors — they know the product, they know the users, they’ve got the context.

A React-centric docs stack quietly pushes them out. Not dramatically. Just gradually. They stop submitting PRs because they don’t want to accidentally break something. They ask engineers to make edits. They work in Google Docs and hand things off. The contribution surface narrows to whoever feels comfortable in the codebase, and your docs quality pays for it.

Versioning sounds better than it is

Yes, Docusaurus has versioning. Yes, you can snapshot your docs for each release.

What the feature demos don’t show you is what happens six months in when you’ve got four supported versions and you realize that fixing a typo in a shared section means finding and updating that text in four different places. Or that a navigation change affects the entire version history. Or that your versioned_docs/ directory is now larger than your actual codebase and equally intimidating to touch.

“Versioned docs” and “maintainable versioned docs” are not the same thing. Docusaurus gives you the former without necessarily helping you with the latter.

Search is great — until it isn’t

Docusaurus’s Algolia DocSearch integration is genuinely excellent and easy to set up. It’s one of the real advantages of the platform, and I’m not going to pretend otherwise.

But it’s also a dependency. Algolia DocSearch is free for open source projects and qualifying sites; for everyone else it’s a paid service. If your budget changes, your search changes. MkDocs + Material ships with a built-in search that’s fast, works offline, requires no external service, and is good enough for most teams. It’s not Algolia — but “not Algolia” and “bad” are not the same thing.

More importantly: search is one feature. It doesn’t justify a docs stack that creates friction everywhere else.

The Better Default: MkDocs + Material

I want to be clear about what I’m recommending here because it matters.

I’m not saying “use MkDocs + Material because it’s objectively superior in every dimension.” I’m saying use MkDocs + Material because it fails gracefully in the ways most teams need, and it keeps your team focused on the right things.

Here’s the core difference in how these two tools think about docs:

Docusaurus architecture for a typical team
flowchart TD A[Writers + Engineers] --> B[Markdown + MDX] B --> C[Docusaurus build] C --> D[React theme + swizzled components] D --> E[Static docs site] F[Custom plugins + directives] --> C G[Frontend maintenance time] --> D

The content layer stays close to the React/theme layer, which is why customization power often turns into maintenance burden.

MkDocs + Material architecture for a typical team
flowchart TD A[Writers + Engineers] --> B[Markdown] B --> C[MkDocs build] H[mkdocs.yml navigation + config] --> C I[Material theme + lightweight plugins] --> C C --> D[Static docs site] J[Lower frontend maintenance burden] --> D

The system stays more content-first: Markdown, configuration, theme, and plugins remain simpler and easier for mixed-skill teams to own.

Docusaurus pulls the docs toward the code. MkDocs + Material keeps the code away from the docs. That’s the whole argument, really.

Here’s what a typical MkDocs + Material setup actually looks like. This is a real mkdocs.yml for a mid-sized project:

site_name: My Project Docs
site_url: https://docs.myproject.com
repo_url: https://github.com/myorg/myproject

theme:
  name: material
  palette:
    - scheme: default
      primary: indigo
      toggle:
        icon: material/brightness-7
        name: Switch to dark mode
    - scheme: slate
      primary: indigo
      toggle:
        icon: material/brightness-4
        name: Switch to light mode
  features:
    - navigation.tabs
    - navigation.sections
    - search.highlight
    - content.code.copy

plugins:
  - search
  - awesome-pages

markdown_extensions:
  - admonitions
  - pymdownx.highlight
  - pymdownx.superfences
  - pymdownx.tabbed:
      alternate_style: true

That’s it. Navigation, search, dark mode, syntax highlighting, tabbed code blocks, admonitions — all from a config file. No React. No swizzling. No src/components/. A writer who has never touched a JavaScript project can understand and modify this.

With MkDocs + Material:

  • Your content is plain Markdown. It will still be plain Markdown when you eventually move to your next tool.
  • Your theme is configuration, not code. Non-engineers can reason about it.
  • Your navigation lives in mkdocs.yml or an awesome-pages config — boring in exactly the right way.
  • Writers can contribute without worrying they’ll break the build.
  • Upgrades don’t require auditing custom components for breakage.

Is it less flashy? Yes. Does the demo look as impressive? No. Does that matter when you’re six months in and everything still works and your whole team can edit docs without filing tickets? Absolutely not.

→ Where to start: Material for MkDocs — Getting Started. Install is two commands, config is one file, and the default output is clean enough to ship the same day.

The Direct Comparison

What actually mattersDocusaurusMkDocs + Material
Looks impressive in a demo✅ Yes⚠️ More restrained
Content stays portable❌ MDX coupling✅ Plain Markdown
Writers can contribute without React knowledge❌ Often not✅ Usually yes
Maintenance burden stays low❌ Accumulates✅ Usually low
Upgrades are low-risk❌ Often painful✅ Usually smooth
Stays boring in the good way❌ Invites complexity✅ Enforces simplicity
Built-in search (no external service)⚠️ Algolia (free tier has limits)✅ Built-in, works offline
i18n / localization✅ Strong support⚠️ Workable but limited
API reference rendering⚠️ Manual or plugin-dependent⚠️ Manual or plugin-dependent
Right for engineering-led dev portals✅ Often⚠️ Sometimes
Right for most normal docs teams❌ Usually not✅ Usually yes

The i18n row is worth noting: if you’re building docs that need to ship in six languages with right-to-left support and locale-aware routing, Docusaurus is genuinely better at that. Same with complex API reference use cases — neither tool handles them elegantly without additional tooling, but Docusaurus at least gives you more surface area to customize your way to a solution.

Both tools have real ceilings. Docusaurus accumulates debt through React coupling. MkDocs + Material accumulates debt through plugin conventions and static-site limitations. MkDocs just tends to fail more gracefully and more visibly when it does.

When Docusaurus Is Actually the Right Call

There are teams for whom Docusaurus is genuinely the right answer. But it’s a specific profile, and it’s worth being honest about whether you actually fit it.

Docusaurus makes sense when:

  • The docs experience is a product feature. You need interactive code playgrounds, live API explorers, or version-aware UI behavior that goes beyond navigation. Think Stripe’s API reference, where the docs are deeply integrated with live credential injection and runnable examples. That level of interactivity is a legitimate React application, not a documentation site that got fancy.
  • You have dedicated frontend capacity for the docs infra. Not “engineers who can help when needed” — actual ownership. Someone whose job includes maintaining the theme, reviewing component changes, and handling upgrades. If that person doesn’t exist, neither does the plan for keeping the site healthy.
  • Your audience is exclusively developers and the content is heavily code-centric. SDKs, CLIs, APIs with multi-language code samples and complex version trees. Docusaurus was built for this and it shows.
  • You need strong i18n. Multiple locales, right-to-left languages, locale-aware routing — Docusaurus handles this much better than MkDocs.

If all four of those are true, Docusaurus earns its complexity. If you’re nodding at one or two of them and squinting at the others, that’s a signal worth paying attention to.

Already on Docusaurus?

If you’re reading this from inside an existing Docusaurus setup, the question isn’t whether you made the wrong call — it’s whether moving now makes sense, and how to limit the damage in the meantime.

Early (under six months, under 100 pages): Migration is cheap. The earlier you move, the less MDX coupling you’ve accumulated. A script can strip most component tags to plain Markdown admonitions in an afternoon. mkdocs.yml takes an hour to get right. The window is open, but it closes fast.

Established (200+ pages, custom components, versioning in use): A full migration is probably not worth the disruption. Contain the damage instead: stop adding custom components, prefer plain Markdown wherever possible, and document what each swizzled piece does before the person who built it leaves. When the next major Docusaurus upgrade breaks your theme, that’s your natural decision point.

Evaluating whether to move: Run both on a real slice of your docs — not samples, but content your team actually writes and edits. See which one your non-engineer contributors use without being prompted.

One rule that helps in all three cases: treat plain Markdown as the floor. Every custom component you don’t add is a migration problem you won’t have later.

The Bottom Line

Docusaurus wins evaluations because it looks great and feels familiar to engineers. It loses the long game because it slowly turns docs into a frontend project, narrows who can contribute, and accumulates the kind of maintenance debt that’s hard to see coming until it’s already there.

MkDocs + Material isn’t exciting. It’s not going to wow anyone in a demo. It’s going to let your whole team write docs, keep your content portable, survive upgrades without drama, and stay out of your way while you focus on the thing that actually matters: the documentation itself.

Start with MkDocs + Material. Move to something more complex only when you hit a real, specific limit that justifies the added overhead — not because the demo looked good.