Skip to main content

Developer Documentation Site — Best Practices Guide

For agents or developers building a full doc site targeting a developer audience. Tech approach: use an existing tool (Docusaurus / VitePress / Nextra).


1. Choose Your Tool

CriteriaDocusaurusVitePressNextra
FrameworkReactVue 3React / Next.js
Best forLarge OSS projects, many sectionsLightweight, API refAlready on Next.js
Versioning✅ Built-inManualManual
i18n✅ Built-in✅ Built-inPlugin
Build speedModerateVery fast (Vite)Fast
SearchAlgolia built-inAlgolia pluginFlexsearch

Quick decision:

  • Full doc site with versioning → Docusaurus
  • Lightweight API reference, speed is priority → VitePress
  • Codebase already uses Next.js → Nextra

Bootstrap Docusaurus

npx create-docusaurus@latest my-docs classic --typescript
cd my-docs
npm run start

Bootstrap VitePress

npx vitepress init
npm run docs:dev

2. Content Structure — The Diátaxis Model

Split all content into 4 types. Never mix them on the same page.

┌─────────────────────────────────────────────────────┐
│ LEARNING │
│ │
│ TUTORIAL │ API REFERENCE │
│ Step-by-step guide │ Technical lookup │
│ → "Build first app" │ → Endpoints, types │
│ │ │
│ P R A C T I C A L ── + ──── T H E O R E T I C A L│
│ │ │
│ HOW-TO GUIDE │ EXPLANATION │
│ Solve a specific task │ Concepts & architecture│
│ → "Setup OAuth 2.0" │ → "How auth works" │
│ │
│ WORKING │
└─────────────────────────────────────────────────────┘

Rules for each type

Tutorial

  • Always have a clear, visible output after each step ("After this step, you will see...")
  • Short sentences, lots of code blocks, no lengthy theory
  • Assume the reader knows nothing, but has already set up their environment
  • Open with: "In this tutorial, you will build X"

How-to Guide

  • Open with: "In this guide, you will learn how to X"
  • One guide = one specific goal
  • No need to explain why — just what to do
  • Can assume the reader already knows the basics

API Reference

  • Auto-generate from OpenAPI spec whenever possible (use Redocly or Stoplight)
  • Every endpoint needs: one-line description, params, real request/response example, error codes
  • Do not explain workflows — only describe behavior
  • Always include type definitions for every field

Explanation

  • Explains "why" and "how" at a conceptual level
  • No instructions, no step-by-step code
  • Use when the team keeps getting asked the same architecture question

3. Directory Structure

Docusaurus

my-docs/
├── docs/
│ ├── getting-started/
│ │ ├── introduction.md ← What & Why (not How)
│ │ ├── quickstart.md ← Working output in < 5 minutes
│ │ └── installation.md
│ ├── tutorials/
│ │ └── build-first-app.md
│ ├── guides/ ← How-to
│ │ ├── authentication.md
│ │ ├── pagination.md
│ │ └── error-handling.md
│ ├── concepts/ ← Explanation
│ │ ├── architecture.md
│ │ └── data-model.md
│ └── api/ ← Reference
│ ├── endpoints.md
│ └── errors.md
├── blog/ ← Changelog, release notes
├── src/
│ ├── components/ ← Custom React components
│ └── css/
│ └── custom.css
├── static/
│ └── img/
└── docusaurus.config.ts

VitePress

docs/
├── .vitepress/
│ └── config.ts
├── getting-started.md
├── guide/
│ ├── index.md
│ └── authentication.md
└── api/
└── index.md

4. Writing Content

Core principles

  1. Devs don't read — they scan. Use headings, code blocks, and bullet points.
  2. One page = one purpose. Never mix a tutorial with a reference.
  3. Code examples must run. Test before publishing.
  4. Use realistic data. Avoid foo, bar, example.com where possible.

Code Blocks

<!-- ✅ CORRECT: language tag + explanatory comment + realistic data -->
```javascript
// Fetch a user by ID
const response = await fetch('https://api.yourapp.com/users/u_123', {
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
}
});

const user = await response.json();
// { id: "u_123", name: "Jane Smith", email: "jane@example.com" }
```

<!-- ❌ WRONG: no language tag, no context -->
```
fetch('/users/123')
```

Callouts / Admonitions

Use to highlight important information:

:::note
Supplementary info — safe to skip without breaking anything.
:::

:::tip
A better approach — recommended.
:::

:::warning
Pay attention — incorrect usage may cause errors.
:::

:::danger
Critical — may result in data loss or a security risk.
:::
note

Supplementary info — safe to skip without breaking anything.

tip

A better approach — recommended.

warning

Pay attention — incorrect usage may cause errors.

danger

Critical — may result in data loss or a security risk.

File naming convention

# Use kebab-case. No underscores, no camelCase.
✅ getting-started.md
✅ api-authentication.md
❌ GettingStarted.md
❌ api_authentication.md

5. Navigation & Information Architecture

// docusaurus.config.ts
const sidebars = {
docs: [
{
type: 'category',
label: 'Getting Started',
collapsed: false, // Keep first section open by default
items: [
'getting-started/introduction',
'getting-started/quickstart',
'getting-started/installation',
],
},
{
type: 'category',
label: 'Guides',
items: [
'guides/authentication',
'guides/pagination',
],
},
{
type: 'category',
label: 'API Reference',
items: [{ type: 'autogenerated', dirName: 'api' }],
},
],
};
  • No more than 3 levels deep in the sidebar
  • First section is always Getting Started, never collapsed
  • API Reference goes at the bottom of the sidebar
  • Put the most important page first within each section

Use Algolia DocSearch — free for open source, the gold standard for dev docs.

# Apply at: https://docsearch.algolia.com/apply/
# Once approved, add to your config:
// docusaurus.config.ts
themeConfig: {
algolia: {
appId: 'YOUR_APP_ID',
apiKey: 'YOUR_SEARCH_API_KEY', // Search-only key (safe to expose publicly)
indexName: 'YOUR_INDEX_NAME',
contextualSearch: true, // Filters results by current version
},
}

No Algolia yet? Use @easyops-cn/docusaurus-search-local for offline/local search.


7. Versioning

Use Docusaurus's built-in versioning. Do not manage this manually.

# Create a new version (snapshot of the current docs/ folder)
npm run docusaurus docs:version 2.0.0

# Resulting structure:
# versioned_docs/version-1.0.0/ ← frozen
# docs/ ← "next" (work in progress)

Rules:

  • Keep at most 2 old versions in the sidebar
  • Always show a banner on old versions: "You are viewing docs for v1.x. View latest."
  • Avoid versioning the API reference if possible — use a Deprecated badge instead

8. Developer UX Details

Must-haves

FeatureHow to implement
Copy button on code blocksBuilt into Docusaurus/VitePress — do not disable
Dark modeEnable as default (defaultMode: 'dark')
"Edit this page" linkPoint to the GitHub repo
BreadcrumbEnable in config
Last updated dateUse git timestamps
SearchAlgolia DocSearch

Default dark mode config

// docusaurus.config.ts
themeConfig: {
colorMode: {
defaultMode: 'dark',
disableSwitch: false, // Still let users toggle
respectPrefersColorScheme: true,
},
}

Edit this page

// docusaurus.config.ts
presets: [
['classic', {
docs: {
editUrl: 'https://github.com/your-org/your-repo/tree/main/',
showLastUpdateTime: true,
showLastUpdateAuthor: false,
},
}],
],

9. Auto-generate API Reference

Never write API reference by hand if you have an OpenAPI spec.

# Install the plugin
npm install docusaurus-plugin-openapi-docs docusaurus-theme-openapi-docs
// docusaurus.config.ts
plugins: [
[
'docusaurus-plugin-openapi-docs',
{
id: 'api',
docsPluginId: 'classic',
config: {
petstore: {
specPath: 'openapi/openapi.yaml',
outputDir: 'docs/api',
sidebarOptions: {
groupPathsBy: 'tag',
},
},
},
},
],
],
# Generate docs from spec
npm run docusaurus gen-api-docs all

10. SEO & Meta

---
title: Authentication Guide
description: Learn how to authenticate API requests using Bearer tokens and API keys.
keywords: [authentication, api key, bearer token, oauth]
---
// docusaurus.config.ts
themeConfig: {
metadata: [
{ name: 'og:type', content: 'website' },
],
},

11. Deployment

// vercel.json
{
"buildCommand": "npm run build",
"outputDirectory": "build",
"framework": "docusaurus2"
}

GitHub Pages

# .github/workflows/deploy.yml
name: Deploy to GitHub Pages
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Required for git last-updated timestamps
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npm run build
- uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./build

12. Pre-launch Checklist

Content

  • Introduction clearly answers "What", "Why", and "Who is this for"
  • Quickstart delivers a working output in under 5 minutes
  • Every page belongs to exactly one of the 4 types (Tutorial / How-to / Reference / Explanation)
  • All code blocks have a language tag
  • Code examples have been tested and run successfully
  • No broken links (check with npx linkinator build --recurse)

Technical

  • Search is set up (Algolia or local)
  • Dark mode works correctly
  • Mobile responsive
  • "Edit this page" points to the correct GitHub location
  • Sitemap is generated (/sitemap.xml)
  • 404 page has a link back to the home page

UX

  • Copy button works on all code blocks
  • Sidebar is no more than 3 levels deep
  • Breadcrumb displays correctly
  • Page loads fast (under 3s on a slow 3G connection)

13. Build & Maintenance Workflow

1. Write OpenAPI spec → auto-generate API Reference

2. Write the Quickstart tutorial first
(Attract and retain new users)

3. Write How-to guides based on real support tickets
(Address the most frequently asked questions)

4. Write Explanations when the team keeps asking "why"

5. Review: ask a newcomer to read and follow along
(If they get stuck → fix the doc, not the reader)

6. Deploy → monitor search queries with no results
(Zero-result queries = gaps that need to be filled)

Reference Resources