Docusaurus Documentation Site Generator: Build Professional Docs in 2026
Docusaurus Documentation Site Generator: Build Professional Docs in 2026
Docusaurus is an open-source static site generator built by Meta (Facebook) specifically for documentation websites. It is used by React, Babel, Jest, Redux, Ionic, and thousands of SaaS companies to power their documentation, API references, and knowledge bases. Docusaurus converts Markdown and MDX files into a fast, SEO-optimized, accessible documentation website with search, versioning, internationalization, and a built-in blog system. It is free, open-source, and deployable to any static host (Vercel, Netlify, GitHub Pages, Cloudflare Pages). This guide covers the complete setup from installation to production deployment with real code examples, plugin development, and monetization strategies.
Why Docusaurus in 2026
The documentation site generator market has several options. Here is how Docusaurus compares.
| Tool | Built With | Markdown | Versioning | i18n | Search | Blog | Cost |
|---|---|---|---|---|---|---|---|
| Docusaurus | React/MDX | MDX (Markdown + JSX) | Yes (built-in) | Yes (60+ locales) | Algolia/local | Yes | Free |
| MkDocs Material | Python | Markdown | Yes (mike) | Yes (i18n) | Native (lunr) | Plugin | Free |
| VitePress | Vue/MDX | Markdown | No | Yes | Native (minisearch) | No | Free |
| GitBook | Proprietary | Markdown | Yes | Yes | Native | No | Free (public) / $8.25/user/mo |
| Read the Docs | Python | reStructuredText/MD | Yes | Yes | Native | No | Free (public) / $50/mo |
| Sphinx | Python | reStructuredText | Yes | Yes | Native | No | Free |
| Docsify | JS (runtime) | Markdown | No | Yes | Native | Plugin | Free |
| Astro Starlight | Astro | MDX | No | Yes | Pagefind | Yes | Free |
Docusaurus wins for projects that need: React-based customization, MDX (embed React components in Markdown), built-in versioning, internationalization, and a blog alongside docs. It is the most feature-complete documentation generator.
Who Uses Docusaurus
| Company/Project | Documentation URL | Daily Visitors (est.) |
|---|---|---|
| React | react.dev | 500K+ |
| Babel | babeljs.io | 50K+ |
| Jest | jestjs.io | 30K+ |
| Redux | redux.js.org | 20K+ |
| Ionic Framework | ionicframework.com/docs | 40K+ |
| Supabase | supabase.com/docs | 15K+ |
| Fastify | fastify.dev | 5K+ |
| CrowdStrike Falcon | (internal docs) | N/A |
Step 1: Installation and Project Setup
1.1 Prerequisites
- Node.js 18+ (20+ recommended)
- npm, yarn, or pnpm
- Basic knowledge of Markdown and optionally React
# Check Node.js version
node --version
# v20.x.x or later recommended
# Install pnpm (recommended for Docusaurus)
npm install -g pnpm
1.2 Create a New Docusaurus Site
# Scaffold a new Docusaurus project
npx create-docusaurus@latest my-docs classic
# Or with TypeScript
npx create-docusaurus@latest my-docs classic --typescript
cd my-docs
npm install
1.3 Project Structure
my-docs/
โโโ blog/ # Blog posts (Markdown)
โ โโโ 2026-10-06-welcome.md
โโโ docs/ # Documentation pages
โ โโโ intro.md
โ โโโ tutorial-basics/
โ โ โโโ _category_.json
โ โ โโโ create-a-page.md
โ โ โโโ create-a-document.md
โ โโโ tutorial-extras/
โโโ src/ # Custom React components and pages
โ โโโ components/
โ โโโ css/
โ โ โโโ custom.css
โ โโโ pages/
โ โโโ index.tsx # Home page
โ โโโ index.module.css
โโโ static/ # Static assets (images, favicons)
โ โโโ img/
โโโ docusaurus.config.ts # Main configuration
โโโ sidebars.ts # Sidebar navigation config
โโโ package.json
โโโ tsconfig.json
1.4 Start the Dev Server
npm run start
# or
npm run start -- --port 3000
# Output:
# [INFO] Docusaurus version: 3.8
# [SUCCESS] Docusaurus website: 3000
# [INFO] Open URL in browser: http://localhost:3000
Your documentation site is now live at http://localhost:3000. Hot module replacement (HMR) updates the page when you edit any Markdown or React file.
1.5 Build for Production
npm run build
# Output:
# [INFO] Docusaurus version: 3.8
# [SUCCESS] Docusaurus website: 3000
# [INFO] Build assets:
# - main route: /
# - docs route: /docs/*
# - blog route: /blog/*
# [SUCCESS] Website will be built in /build directory
The static site is generated in the build/ directory. Deploy this to any static host.
1.6 Preview the Production Build
npm run serve
# Serves the build/ directory on http://localhost:3000
Step 2: Configuration
2.1 Main Config File
Edit docusaurus.config.ts:
import { themes as prismThemes } from "prism-react-renderer";
import type { Config } from "@docusaurus/types";
import type * as Preset from "@docusaurus/preset-classic";
const config: Config = {
title: "My SaaS Docs",
tagline: "Documentation for My SaaS",
favicon: "img/favicon.ico",
// Set the production url of your online site
url: "https://docs.mysaas.com",
// Set the /<baseUrl>/ pathname under which your site is served
baseUrl: "/",
// GitHub pages deployment config
// organizationName: "your-org",
// projectName: "my-docs",
// deploymentBranch: "gh-pages",
// trailingSlash: false,
onBrokenLinks: "throw",
onBrokenMarkdownLinks: "warn",
// Even if you don't use i18n, you can use this field
i18n: {
defaultLocale: "en",
locales: ["en", "zh", "ja"],
},
presets: [
[
"classic",
{
docs: {
sidebarPath: "./sidebars.ts",
editUrl: "https://github.com/my-org/my-docs/tree/main",
},
blog: {
showReadingTime: true,
readingTime: ({ content }) =>
Math.ceil(content.split(/\s+/).length / 200),
},
theme: {
customCss: "./src/css/custom.css",
},
} satisfies Preset.ThemeConfig,
] satisfies Preset.Options,
],
themeConfig: {
image: "img/social-card.png",
navbar: {
title: "My SaaS",
logo: { alt: "Logo", src: "img/logo.svg" },
items: [
{ to: "/docs/intro", label: "Docs", position: "left" },
{ to: "/blog", label: "Blog", position: "left" },
{
href: "https://github.com/my-org/my-saas",
label: "GitHub",
position: "right",
},
],
},
footer: {
style: "dark",
links: [
{
title: "Docs",
items: [
{ label: "Getting Started", to: "/docs/intro" },
{ label: "API Reference", to: "/docs/api" },
],
},
{
title: "Community",
items: [
{ label: "Discord", href: "https://discord.gg/my-saas" },
{ label: "Twitter", href: "https://twitter.com/mysaas" },
],
},
{
title: "More",
items: [
{ label: "Blog", to: "/blog" },
{ label: "GitHub", href: "https://github.com/my-org/my-saas" },
],
},
],
copyright: `Copyright ยฉ ${new Date().getFullYear()} My SaaS. Built with Docusaurus.`,
},
prism: {
theme: prismThemes.github,
darkTheme: prismThemes.dracula,
},
algolia: {
appId: "YOUR_APP_ID",
apiKey: "YOUR_API_KEY",
indexName: "mysaas",
contextualSearch: true,
},
} satisfies Preset.ThemeConfig,
};
export default config;
2.2 Sidebar Configuration
Edit sidebars.ts:
import type { SidebarsConfig } from "@docusaurus/plugin-content-docs";
const sidebars: SidebarsConfig = {
// By default, Docusaurus generates a sidebar from the docs folder structure
tutorialSidebar: [{ type: "autogenerated", dirName: "." }],
// Or define a custom sidebar
customSidebar: [
"intro",
{
type: "category",
label: "Getting Started",
items: ["getting-started/installation", "getting-started/quick-start"],
},
{
type: "category",
label: "Guides",
items: [
"guides/authentication",
"guides/database",
"guides/deployment",
"guides/troubleshooting",
],
},
{
type: "category",
label: "API Reference",
items: [
{
type: "category",
label: "REST API",
items: ["api/rest/overview", "api/rest/endpoints", "api/rest/errors"],
},
{
type: "category",
label: "SDKs",
items: ["api/sdks/javascript", "api/sdks/python"],
},
],
},
{
type: "category",
label: "FAQ",
items: ["faq/general", "faq/billing", "faq/security"],
},
],
};
export default sidebars;
2.3 Category Metadata
Create _category_.json in any docs subfolder:
{
"label": "Getting Started",
"position": 2,
"link": {
"type": "generated-index",
"description": "Everything you need to get started with My SaaS"
}
}
Step 3: Writing Documentation with MDX
MDX is Markdown with JSX. You can embed React components inside Markdown files.
3.1 Basic Markdown
---
sidebar_position: 1
title: Introduction
description: Learn what My SaaS is and how it can help your business.
slug: /intro
---
# Introduction
My SaaS is a platform that helps you...
## Features
- **Fast**: Sub-100ms response times
- **Scalable**: Handles millions of requests
- **Secure**: SOC 2 Type II certified
## Quick Start
\`\`\`bash
npm install @mysaas/sdk
\`\`\`
\`\`\`javascript
import { MySaaS } from "@mysaas/sdk";
const client = new MySaaS({ apiKey: "your-key" });
const result = await client.getData();
\`\`\`
> **Note:** You need an API key to use the SDK. [Get one here](/docs/getting-started/api-keys).
3.2 MDX with React Components
---
title: Pricing
description: Pricing plans and features comparison.
---
import PricingTable from "@site/src/components/PricingTable";
import Callout from "@site/src/components/Callout";
<Callout type="info">
All plans include a 14-day free trial. No credit card required.
</Callout>
# Pricing
Choose the plan that fits your needs:
<PricingTable />
| Plan | Price | Requests | Storage | Support |
|------|-------|----------|---------|---------|
| Free | $0 | 10K/mo | 1GB | Community |
| Pro | $29/mo | 1M/mo | 50GB | Email |
| Team | $99/mo | 10M/mo | 500GB | Priority |
| Enterprise | Custom | Unlimited | Unlimited | Dedicated |
<Callout type="warning">
The Free plan is rate-limited to 100 requests per minute.
</Callout>
3.3 Create the React Components
// src/components/PricingTable.tsx
import React from "react";
const plans = [
{ name: "Free", price: "$0", requests: "10K/mo", storage: "1GB", color: "gray" },
{ name: "Pro", price: "$29/mo", requests: "1M/mo", storage: "50GB", color: "blue" },
{ name: "Team", price: "$99/mo", requests: "10M/mo", storage: "500GB", color: "purple" },
];
export default function PricingTable() {
return (
<div className="grid grid-cols-3 gap-4">
{plans.map((plan) => (
<div key={plan.name} className="card">
<h3>{plan.name}</h3>
<p className="text-2xl font-bold">{plan.price}</p>
<ul>
<li>{plan.requests} requests</li>
<li>{plan.storage} storage</li>
</ul>
</div>
))}
</div>
);
}
// src/components/Callout.tsx
import React from "react";
export default function Callout({ type = "info", children }) {
const colors = {
info: "blue",
warning: "yellow",
danger: "red",
success: "green",
};
return (
<div className={`callout callout-${colors[type]}`}>
{children}
</div>
);
}
3.4 Docs Frontmatter Options
| Field | Type | Default | Description |
|---|---|---|---|
title |
string | From H1 | Page title |
description |
string | First paragraph | SEO description |
slug |
string | From filename | URL path |
sidebar_position |
number | From filename | Order in sidebar |
sidebar_label |
string | From title | Sidebar label |
sidebar_class |
string | โ | CSS class for sidebar item |
sidebar_custom_props |
object | โ | Custom props for sidebar |
displayed_sidebar |
string | โ | Which sidebar to show |
tags |
array | [] | Tags for the page |
image |
string | โ | Social card image |
keywords |
array | [] | SEO keywords |
draft |
boolean | false | Exclude from production |
unlisted |
boolean | false | Exclude from search and sitemap |
Step 4: Versioning Documentation
Docusaurus has built-in support for documentation versioning. This is critical for SaaS products that evolve.
4.1 Create a Version
# Cut a new version (saves current docs/ as a snapshot)
npm run docusaurus docs:version 1.0.0
# Output:
# docs
# โโโ 1.0.0
# โโโ intro.md
# โโโ getting-started
# โโโ current
# โโโ intro.md (working copy, not versioned)
4.2 Version Configuration
Edit docusaurus.config.ts:
docs: {
sidebarPath: "./sidebars.ts",
editUrl: "https://github.com/my-org/my-docs/tree/main",
versions: {
current: {
label: "Next (Unreleased)",
badge: true,
},
"1.0.0": {
label: "v1.0",
badge: true,
},
},
lastVersion: "1.0.0", // default version shown
},
4.3 Version Display
Users see a version dropdown in the navbar. They can switch between versions. Each version has its own sidebar and pages. Old versions are read-only (no edit URL).
4.4 Version Management
| Action | Command |
|---|---|
| Create new version | npm run docusaurus docs:version 2.0.0 |
| List versions | ls versioned_docs/ |
| Delete a version | rm -rf versioned_docs/version-1.0.0 versioned_sidebars/version-1.0.0-sidebars.json then update versions config |
| Rename a version | Update label in config |
Step 5: Internationalization (i18n)
Docusaurus supports 60+ locales out of the box.
5.1 Configure i18n
In docusaurus.config.ts:
i18n: {
defaultLocale: "en",
locales: ["en", "zh", "ja", "de", "fr"],
localeConfigs: {
en: { label: "English", direction: "ltr" },
zh: { label: "็ฎไฝไธญๆ", direction: "ltr" },
ja: { label: "ๆฅๆฌ่ช", direction: "ltr" },
de: { label: "Deutsch", direction: "ltr" },
fr: { label: "Franรงais", direction: "ltr" },
},
},
5.2 Translate Content
Create translated versions of docs:
i18n/
โโโ en/
โ โโโ docusaurus-plugin-content-docs/
โ โ โโโ current/ (or copy of docs/)
โ โ โโโ intro.md
โ โโโ docusaurus-plugin-content-blog/
โ โโโ 2026-10-06-welcome.md
โโโ zh/
โ โโโ docusaurus-plugin-content-docs/
โ โ โโโ current/
โ โ โโโ intro.md (translated)
โ โโโ code.json (UI strings translated)
โโโ ja/
5.3 Start in a Specific Locale
# Start dev server in Chinese
npm run start -- --locale zh
# Build all locales
npm run build
# Build only Chinese
npm run build -- --locale zh
5.4 Translation Workflow with Crowdin
For community translations, use Crowdin:
- Create a project at crowdin.com
- Install
@docusaurus/plugin-ideal-imageanddocusaurus-plugin-crowdin - Configure the plugin with your Crowdin project ID
- Translators work in Crowdin's web editor
- Sync translations via CLI:
crowdin upload sources/crowdin download translations
Step 6: Search Integration
6.1 Algolia DocSearch (Free for Open Source)
- Apply at docsearch.algolia.com
- If approved, Algolia crawls your site and provides search for free
- Add to config:
themeConfig: {
algolia: {
appId: "YOUR_APP_ID",
apiKey: "YOUR_SEARCH_API_KEY",
indexName: "mysaas",
contextualSearch: true,
// Optional: Replace placeholders in search results
replaceSearchResultPathname: (pathname) =>
pathname.replace("/docs/", "/guide/"),
},
},
6.2 Local Search (No External Service)
For privacy-focused or small sites, use local search:
npm install @easyops-cn/docusaurus-search-local
// docusaurus.config.ts
themes: [
[
require.resolve("@easyops-cn/docusaurus-search-local"),
{
hashed: true,
language: ["en", "zh"],
indexDocs: true,
indexBlog: true,
indexPages: true,
docsRouteBasePath: "docs",
blogRouteBasePath: "blog",
},
],
],
This generates a search index at build time. Search works offline, no server needed.
6.3 Search Comparison
| Feature | Algolia DocSearch | Local Search Plugin |
|---|---|---|
| Cost | Free (OSS) / $1+ (commercial) | Free |
| Indexing | Algolia servers (always fresh) | Build time (static) |
| Speed | ~50ms (CDN) | ~100ms (local) |
| Offline | No | Yes |
| Multi-language | Yes | Yes |
| Setup difficulty | Medium (apply, wait) | Low (install plugin) |
Step 7: Plugins and Themes
7.1 Official Plugins
| Plugin | Purpose | Install |
|---|---|---|
@docusaurus/plugin-content-docs |
Documentation pages | Built-in |
@docusaurus/plugin-content-blog |
Blog | Built-in |
@docusaurus/plugin-content-pages |
Standalone pages | Built-in |
@docusaurus/plugin-sitemap |
XML sitemap | Built-in |
@docusaurus/plugin-google-analytics |
GA tracking | Built-in |
@docusaurus/plugin-google-tag-manager |
GTM | Built-in |
@docusaurus/plugin-ideal-image |
Lazy-loaded responsive images | npm install @docusaurus/plugin-ideal-image |
@docusaurus/plugin-pwa |
Progressive Web App | npm install @docusaurus/plugin-pwa |
@docusaurus/plugin-client-redirects |
URL redirects | npm install @docusaurus/plugin-client-redirects |
@docusaurus/plugin-ideal-image |
Image optimization | Built-in |
7.2 Community Plugins
| Plugin | Purpose |
|---|---|
docusaurus-plugin-redoc |
OpenAPI documentation |
docusaurus-plugin-remark-npm2yarn |
npm/yarn/pnpm tabs |
docusaurus-plugin-openapi-docs |
OpenAPI spec rendering |
docusaurus-plugin-sass |
Sass/SCSS support |
docusaurus-plugin-typedoc |
TypeScript API docs from TypeDoc |
docusaurus-plugin-matomo |
Matomo analytics |
docusaurus-plugin-image-zoom |
Image zoom on click |
7.3 Custom Plugin Example
// plugins/remark-plugin.ts
import { Plugin } from "@docusaurus/types";
const plugin: Plugin = {
name: "docusaurus-remark-callout",
async contentLoaded({ contentActions }) {
// Register remark plugin
},
async markdownProcessor({ content }) {
// Transform Markdown AST
return content.replace(/:::warning/g, '> โ ๏ธ **Warning:**');
},
};
export default plugin;
7.4 Theme Customization
Customize the look and feel in src/css/custom.css:
:root {
--ifm-color-primary: #2563eb;
--ifm-color-primary-dark: #1d4ed8;
--ifm-color-primary-darker: #1e40af;
--ifm-color-primary-darkest: #1e3a8a;
--ifm-color-primary-light: #3b82f6;
--ifm-color-primary-lighter: #60a5fa;
--ifm-color-primary-lightest: #93c5fd;
--ifm-code-font-size: 95%;
--ifm-font-size-base: 16px;
--ifm-line-height-base: 1.6;
--ifm-heading-font-weight: 700;
--ifm-navbar-height: 64px;
--ifm-navbar-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
}
[data-theme="dark"] {
--ifm-color-primary: #3b82f6;
--ifm-color-primary-dark: #2563eb;
--ifm-background-color: #0d1117;
--ifm-background-surface-color: #161b22;
--ifm-navbar-background-color: #161b22;
--ifm-font-color-base: #e6edf3;
}
/* Custom callout styles */
.callout {
padding: 1rem 1.5rem;
border-radius: 8px;
margin: 1.5rem 0;
}
.callout-blue {
background: #dbeafe;
border-left: 4px solid #3b82f6;
}
[data-theme="dark"] .callout-blue {
background: #1e3a5f;
}
Step 8: Blog System
Docusaurus includes a built-in blog system. Each post is a Markdown file in blog/.
8.1 Create a Blog Post
---
title: "Welcome to My SaaS Blog"
date: 2026-10-06
author: "Siyuan"
description: "Our first blog post about launching My SaaS."
tags: ["announcement", "launch"]
---
# Welcome to My SaaS Blog
Today we're launching My SaaS...

We built My SaaS to solve...
8.2 Blog Frontmatter
| Field | Type | Description |
|---|---|---|
title |
string | Post title |
date |
YYYY-MM-DD | Publish date (determines order) |
author |
string/object | Author name or { name, title, url, image_url } |
description |
string | SEO description |
tags |
array | Tags |
slug |
string | URL slug |
image |
string | Social card image |
draft |
boolean | Exclude from production |
unlisted |
boolean | Hidden from listing but accessible |
hide_table_of_contents |
boolean | Hide TOC |
8.3 Blog Configuration
blog: {
path: "blog",
routeBasePath: "blog",
include: ["*.md", "*.mdx"],
postsPerPage: 10,
blogSidebarCount: "ALL", // or number
blogTitle: "My SaaS Blog",
showReadingTime: true,
feedOptions: {
type: ["rss", "atom"],
title: "My SaaS Blog",
description: "Latest news and tutorials",
copyright: `ยฉ ${new Date().getFullYear()} My SaaS`,
},
sortPosts: "descending",
},
This generates RSS and Atom feeds at /blog/rss.xml and /blog/atom.xml.
Step 9: Deployment
9.1 Deploy to Vercel
- Push your Docusaurus repo to GitHub
- Go to vercel.com โ New Project
- Import your repo
- Framework: Vercel auto-detects Docusaurus
- Build command:
npm run build - Output directory:
build - Click Deploy
Vercel auto-deploys on every push to main. Custom domains are free with SSL.
9.2 Deploy to GitHub Pages
# Configure docusaurus.config.ts
# organizationName: "your-org",
# projectName: "my-docs",
# url: "https://your-org.github.io",
# baseUrl: "/my-docs/",
# deploymentBranch: "gh-pages",
# Deploy
npm run deploy
# Or with GitHub Actions:
# .github/workflows/deploy.yml
# .github/workflows/deploy.yml
name: Deploy Docusaurus to GitHub Pages
on:
push:
branches: [main]
permissions:
contents: read
pages: write
id-token: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- run: npm run build
- uses: actions/upload-pages-artifact@v3
with:
path: build
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
steps:
- uses: actions/deploy-pages@v4
9.3 Deploy to Cloudflare Pages
- Push to GitHub
- Go to Cloudflare Dashboard โ Pages โ Create project
- Connect GitHub repo
- Build command:
npm run build - Build output:
build - Click Deploy
9.4 Deployment Comparison
| Host | Free Tier | Custom Domain | SSL | Build Time | Bandwidth |
|---|---|---|---|---|---|
| Vercel | Yes (100GB) | Yes (free) | Yes | ~30 sec | 100GB/mo |
| GitHub Pages | Yes (unlimited public) | Yes (free) | Yes | ~60 sec | 100GB/mo |
| Cloudflare Pages | Yes (unlimited) | Yes (free) | Yes | ~20 sec | Unlimited |
| Netlify | Yes (100GB) | Yes (free) | Yes | ~30 sec | 100GB/mo |
Step 10: SEO and Analytics
10.1 SEO Optimization
Docusaurus is SEO-optimized by default:
- Server-side rendered (SSG) for fast initial load
- Automatic sitemap.xml generation
- Per-page title and description from frontmatter
- Open Graph and Twitter Card meta tags
- Canonical URLs
- Structured data (JSON-LD) via plugins
Add structured data:
// src/plugins/structured-data.ts
export function generateDocStructuredData(page) {
return {
"@context": "https://schema.org",
"@type": "TechArticle",
headline: page.title,
description: page.description,
author: { "@type": "Organization", name: "My SaaS" },
datePublished: page.date,
dateModified: page.lastUpdated,
};
}
10.2 Google Analytics
themeConfig: {
gtag: {
trackingID: "G-XXXXXXXXXX",
anonymizeIP: true,
},
},
10.3 Google Tag Manager
themeConfig: {
gtm: {
containerId: "GTM-XXXXXXX",
},
},
Step 11: Monetizing Docusaurus Skills
| Method | Effort | Income Potential | Time to First $ |
|---|---|---|---|
| Build docs for SaaS companies | Medium | $1,000-5,000/project | 1-4 weeks |
| Create and sell Docusaurus themes | High | $200-2,000/month | 2-6 months |
| Write Docusaurus tutorials | Medium | $200-1,000/article | 1-2 weeks |
| Docusaurus consulting | Medium | $75-200/hour | 2-4 weeks |
| Open source docs for hire | Medium | $2,000-10,000/project | 2-6 weeks |
Freelance Documentation Services
A practical side hustle: offer documentation services to SaaS companies.
- Target: SaaS companies with poor or no documentation
- Offer: "I will build your complete documentation site with Docusaurus โ $1,999"
- Deliverable: Docusaurus site, 20-30 pages of docs, search, versioning, deployment
- Time: 2-3 weeks part-time
- Tools: Docusaurus + Algolia + Vercel
- Upsell: Ongoing docs maintenance ($300-500/month)
Platforms to find clients: Upwork, Contra, direct outreach to SaaS companies with bad docs.
Action Checklist
- Install Node.js 20+ and pnpm
- Create a Docusaurus project with
npx create-docusaurus@latest - Start the dev server and explore the default site
- Configure
docusaurus.config.tswith your site details - Create your first documentation page in
docs/ - Set up the sidebar navigation in
sidebars.ts - Try MDX by embedding a React component in a Markdown page
- Create a custom React component in
src/components/ - Customize the theme in
src/css/custom.css - Set up the blog system and write your first post
- Add search (Algolia DocSearch or local search plugin)
- Configure i18n with at least 2 locales
- Set up versioning with
npm run docusaurus docs:version - Add Google Analytics or GTM
- Deploy to Vercel, GitHub Pages, or Cloudflare Pages
- Set up a custom domain with SSL
- Create a CI/CD pipeline for auto-deploy
- Write a contribution guide for community docs
Common Pitfalls and Solutions
| Pitfall | Impact | Solution |
|---|---|---|
| Broken links in production | 404 errors, bad SEO | Set onBrokenLinks: "throw" in config |
| Large images slowing build | Slow builds, poor UX | Use @docusaurus/plugin-ideal-image |
| No versioning | Old docs inaccessible | Set up versioning from day one |
| No search | Users can't find content | Add Algolia or local search |
| Too many plugins | Slow build, complexity | Only install plugins you need |
Not setting url and baseUrl |
Broken assets in production | Set these before deploying |
| Not using MDX features | Missed interactivity | Learn MDX and use React components |
| No i18n planning | Hard to add later | Plan locales from the start |
Final Word
Docusaurus is the best open-source documentation site generator for teams that need professional docs, versioning, search, i18n, and a blog โ all in one. It is free, built by Meta, and used by React, Babel, Jest, and thousands of SaaS companies. The setup takes 1-2 hours: install the CLI, scaffold a project, configure the sidebar, write your first page in Markdown or MDX, customize the theme, add search, and deploy to Vercel or GitHub Pages. The built-in versioning lets you maintain docs for multiple product versions simultaneously, and the i18n system supports 60+ languages. For side hustles, Docusaurus skills are monetizable: SaaS companies pay $1,000-5,000 for a complete documentation site, and ongoing maintenance retainerers add $300-500/month. Start with the free template, customize it for your project or a client, and deploy to Vercel for free hosting with a custom domain.
More guides: bsynet.cc