Docusaurus

Collaboration Tool

Docusaurus

Overview

Docusaurus is a powerful static site generator developed by Meta, specifically designed for building documentation sites. Built on React, it comes equipped with all the features needed for technical documentation, including Markdown and MDX support, version management, internationalization, and powerful search capabilities. It's designed to help developers quickly build beautiful, maintainable documentation sites.

Details

Docusaurus is a tool that makes it easy to build sites that integrate technical documentation, product documentation, and blogs. It's customizable as React components, and by using MDX, you can embed React components within Markdown. With built-in versioning capabilities, you can manage documentation for multiple versions simultaneously, and through Algolia integration, it provides fast search functionality. Its plugin architecture allows for flexible feature extensions.

Key Features

  • Markdown/MDX Support: Integration of Markdown and React components
  • Versioning: Multi-version documentation management
  • Internationalization (i18n): Native support for multilingual documentation
  • Search Functionality: Integration with Algolia DocSearch
  • Plugin System: Flexible feature extensions
  • Theme Customization: Design changes to match branding
  • Blog Feature: Blog integrated with documentation
  • Auto Deploy: Integration with GitHub Pages, Netlify, Vercel

Plugin API Overview

Plugin Structure

module.exports = function(context, options) {
  return {
    name: 'my-plugin',
    async loadContent() {
      // Load content
    },
    async contentLoaded({content, actions}) {
      // Actions after content processing
    },
    configureWebpack(config, isServer, utils) {
      // Customize Webpack configuration
    }
  };
};

Lifecycle Hooks

// Main lifecycle methods
{
  loadContent(): Promise<any>
  contentLoaded({content, actions}): Promise<void>
  postBuild(props): Promise<void>
  configureWebpack(config, isServer, utils): object
  getThemePath(): string
  getClientModules(): string[]
  injectHtmlTags({content}): object
}

Advantages and Disadvantages

Advantages

  • Development and support by Meta
  • Rich features specialized for documentation
  • Excellent developer experience
  • Fast build and performance
  • SEO optimized
  • Active community
  • Rich plugin ecosystem

Disadvantages

  • React knowledge required (for advanced customization)
  • Static sites only (limited dynamic features)
  • Build time can be long (for large sites)
  • Plugin development is complex
  • API documentation-specific features require manual implementation
  • Limited design customization

Practical Examples

1. Basic Docusaurus Project Setup

# Create project
npx create-docusaurus@latest my-docs classic

# Install dependencies
cd my-docs
npm install

# Start development server
npm start

# Production build
npm run build

# Preview built site
npm run serve

2. docusaurus.config.js Configuration

// @ts-check
const lightCodeTheme = require('prism-react-renderer/themes/github');
const darkCodeTheme = require('prism-react-renderer/themes/dracula');

/** @type {import('@docusaurus/types').Config} */
const config = {
  title: 'My Documentation',
  tagline: 'Technical documentation made easy',
  url: 'https://mydocs.example.com',
  baseUrl: '/',
  onBrokenLinks: 'throw',
  onBrokenMarkdownLinks: 'warn',
  favicon: 'img/favicon.ico',
  organizationName: 'myorg',
  projectName: 'mydocs',
  
  i18n: {
    defaultLocale: 'ja',
    locales: ['ja', 'en'],
    localeConfigs: {
      ja: {
        label: '日本語',
        direction: 'ltr',
      },
      en: {
        label: 'English',
        direction: 'ltr',
      },
    },
  },

  presets: [
    [
      'classic',
      /** @type {import('@docusaurus/preset-classic').Options} */
      ({
        docs: {
          sidebarPath: require.resolve('./sidebars.js'),
          editUrl: 'https://github.com/myorg/mydocs/tree/main/',
          remarkPlugins: [],
          rehypePlugins: [],
          showLastUpdateAuthor: true,
          showLastUpdateTime: true,
        },
        blog: {
          showReadingTime: true,
          editUrl: 'https://github.com/myorg/mydocs/tree/main/',
        },
        theme: {
          customCss: require.resolve('./src/css/custom.css'),
        },
      }),
    ],
  ],

  themeConfig:
    /** @type {import('@docusaurus/preset-classic').ThemeConfig} */
    ({
      navbar: {
        title: 'My Docs',
        logo: {
          alt: 'My Docs Logo',
          src: 'img/logo.svg',
        },
        items: [
          {
            type: 'doc',
            docId: 'intro',
            position: 'left',
            label: 'Documentation',
          },
          {to: '/blog', label: 'Blog', position: 'left'},
          {
            href: 'https://github.com/myorg/mydocs',
            label: 'GitHub',
            position: 'right',
          },
          {
            type: 'localeDropdown',
            position: 'right',
          },
        ],
      },
      footer: {
        style: 'dark',
        links: [
          {
            title: 'Documentation',
            items: [
              {
                label: 'Getting Started',
                to: '/docs/intro',
              },
              {
                label: 'API Reference',
                to: '/docs/api',
              },
            ],
          },
        ],
        copyright: `Copyright © ${new Date().getFullYear()} My Organization.`,
      },
      prism: {
        theme: lightCodeTheme,
        darkTheme: darkCodeTheme,
        additionalLanguages: ['rust', 'ruby', 'php'],
      },
      algolia: {
        appId: 'YOUR_APP_ID',
        apiKey: 'YOUR_SEARCH_API_KEY',
        indexName: 'mydocs',
        contextualSearch: true,
      },
    }),
};

module.exports = config;

3. Creating a Custom Plugin

// plugins/custom-plugin.js
module.exports = function (context, options) {
  return {
    name: 'custom-documentation-plugin',
    
    async loadContent() {
      // Load documentation from external API
      const apiDocs = await fetchAPIDocumentation();
      return apiDocs;
    },
    
    async contentLoaded({content, actions}) {
      const {createData, addRoute} = actions;
      
      // Create data file
      const apiDocsPath = await createData(
        'api-docs.json',
        JSON.stringify(content)
      );
      
      // Add new route
      addRoute({
        path: '/api-reference',
        component: '@site/src/components/APIReference',
        props: {
          apiDocsPath,
        },
        exact: true,
      });
    },
    
    configureWebpack(config, isServer, utils) {
      return {
        module: {
          rules: [
            {
              test: /\.yaml$/,
              use: 'yaml-loader',
            },
          ],
        },
        resolve: {
          alias: {
            '@api': path.resolve(__dirname, '../src/api'),
          },
        },
      };
    },
    
    getThemePath() {
      return path.resolve(__dirname, './theme');
    },
    
    injectHtmlTags({content}) {
      return {
        headTags: [
          {
            tagName: 'link',
            attributes: {
              rel: 'preconnect',
              href: 'https://fonts.googleapis.com',
            },
          },
        ],
        preBodyTags: [],
        postBodyTags: [],
      };
    },
  };
};

// Usage example: docusaurus.config.js
module.exports = {
  plugins: [
    ['./plugins/custom-plugin', {
      apiEndpoint: 'https://api.example.com/docs',
    }],
  ],
};

4. MDX Components and Custom Pages

// src/components/APIEndpoint.js
import React from 'react';
import CodeBlock from '@theme/CodeBlock';

export default function APIEndpoint({method, path, description, example}) {
  const methodColors = {
    GET: '#61affe',
    POST: '#49cc90',
    PUT: '#fca130',
    DELETE: '#f93e3e',
  };
  
  return (
    <div className="api-endpoint">
      <div className="api-header">
        <span 
          className="method" 
          style={{backgroundColor: methodColors[method]}}
        >
          {method}
        </span>
        <code className="path">{path}</code>
      </div>
      <p className="description">{description}</p>
      {example && (
        <div className="example">
          <h4>Example</h4>
          <CodeBlock language="json">{example}</CodeBlock>
        </div>
      )}
    </div>
  );
}

// Usage example in documentation (.mdx file)
/*
---
title: API Reference
---

import APIEndpoint from '@site/src/components/APIEndpoint';

# API Reference

## User Management

<APIEndpoint
  method="GET"
  path="/api/users"
  description="Get all users"
  example={`{
  "users": [
    {
      "id": 1,
      "name": "John Doe",
      "email": "[email protected]"
    }
  ]
}`}
/>

<APIEndpoint
  method="POST"
  path="/api/users"
  description="Create a new user"
  example={`{
  "name": "Jane Doe",
  "email": "[email protected]"
}`}
/>
*/

5. Versioning and Localization

# Create new version
npm run docusaurus docs:version 1.0.0

# Directory structure
# versioned_docs/
#   version-1.0.0/
#     intro.md
#     api/
#       overview.md
# versions.json

# Initialize translation files
npm run write-translations -- --locale ja

# i18n directory structure
# i18n/
#   ja/
#     docusaurus-plugin-content-docs/
#       current/
#         intro.md
#       version-1.0.0/
#         intro.md
#     docusaurus-theme-classic/
#       navbar.json
#       footer.json

6. Automated Deployment with GitHub Actions

# .github/workflows/deploy.yml
name: Deploy to GitHub Pages

on:
  push:
    branches:
      - main

jobs:
  deploy:
    name: Deploy to GitHub Pages
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - uses: actions/setup-node@v3
        with:
          node-version: 18
          cache: npm

      - name: Install dependencies
        run: npm ci
        
      - name: Build website
        run: npm run build
        env:
          NODE_ENV: production

      - name: Deploy to GitHub Pages
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./build
          user_name: github-actions[bot]
          user_email: 41898282+github-actions[bot]@users.noreply.github.com

Reference Links