Skip to main content

how-to-write-docs


title: How to Write Documentation description: Best practices for building a developer documentation site using Docusaurus, VitePress, or Nextra. keywords: [docusaurus, vitepress, nextra, documentation, best practices, diataxis]

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" }
fetch('/users/123')

### Callouts / Admonitions

Use to highlight important information:

```markdown
:::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​