Automates docs-as-code workflows with version control, PR reviews, automated testing, linting, link checks, and CI/CD deployment. Compares Docusaurus, MkDocs, Sphinx, Hugo.
npx claudepluginhub melodic-software/claude-code-plugins --plugin documentation-standardsThis skill is limited to using the following tools:
Use this skill when:
Guides MkDocs Material setup with Diataxis framework, mkdocstrings and Griffe for API reference pages, Google-style docstrings, nav structure, code example testing, and deployment to GitHub Pages or ReadTheDocs.
Generates documentation from code including API references, developer guides, READMEs, and architecture overviews. Matches existing styles and avoids overwriting in brownfield codebases.
Share bugs, ideas, or general feedback.
Use this skill when:
Implement documentation-as-code workflows with automated pipelines, version control, and CI/CD integration.
Before implementing docs-as-code:
docs-management skill for documentation patternsDocs-as-Code Principles:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ 1. Version Control โ
โ - Docs live alongside code in the same repository โ
โ - Changes tracked with meaningful commit messages โ
โ - Branch-based workflow for documentation updates โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ 2. Review Process โ
โ - Pull requests for documentation changes โ
โ - Technical review by subject matter experts โ
โ - Style review by technical writers โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ 3. Automated Testing โ
โ - Linting for style and grammar โ
โ - Link validation โ
โ - Build verification โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ 4. Continuous Deployment โ
โ - Automatic publishing on merge โ
โ - Preview deployments for PRs โ
โ - Versioned documentation releases โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
| Tool | Language | Best For | Build Speed |
|---|---|---|---|
| Docusaurus | JS/React | Product docs, versioning | Fast |
| MkDocs | Python | Technical docs, Material theme | Fast |
| Sphinx | Python | API docs, reStructuredText | Medium |
| Hugo | Go | Large sites, speed | Very Fast |
| Astro | JS | Modern sites, MDX | Fast |
| VitePress | JS/Vue | Vue ecosystem | Very Fast |
| Jekyll | Ruby | GitHub Pages native | Medium |
docs/
โโโ docusaurus.config.js # Main configuration
โโโ sidebars.js # Navigation structure
โโโ package.json # Dependencies
โโโ docs/ # Documentation content
โ โโโ intro.md
โ โโโ getting-started/
โ โ โโโ installation.md
โ โ โโโ configuration.md
โ โโโ guides/
โ โ โโโ quick-start.md
โ โ โโโ advanced.md
โ โโโ api/
โ โโโ reference.md
โโโ blog/ # Blog posts (optional)
โโโ src/
โ โโโ components/ # React components
โ โโโ css/ # Custom styles
โ โโโ pages/ # Custom pages
โโโ static/ # Static assets
โ โโโ img/
โโโ versioned_docs/ # Version snapshots
โโโ version-1.0/
โโโ version-2.0/
docs/
โโโ mkdocs.yml # Configuration
โโโ docs/
โ โโโ index.md
โ โโโ getting-started/
โ โ โโโ installation.md
โ โ โโโ configuration.md
โ โโโ user-guide/
โ โ โโโ features.md
โ โโโ reference/
โ โ โโโ api.md
โ โโโ about/
โ โโโ changelog.md
โโโ overrides/ # Theme customization
โ โโโ main.html
โ โโโ partials/
โโโ requirements.txt # Python dependencies
// docusaurus.config.js
const config = {
title: 'Project Name',
tagline: 'Project tagline',
url: 'https://docs.example.com',
baseUrl: '/',
onBrokenLinks: 'throw',
onBrokenMarkdownLinks: 'warn',
favicon: 'img/favicon.ico',
organizationName: 'organization',
projectName: 'project',
i18n: {
defaultLocale: 'en',
locales: ['en'],
},
presets: [
[
'classic',
{
docs: {
sidebarPath: require.resolve('./sidebars.js'),
editUrl: 'https://github.com/org/project/edit/main/docs/',
showLastUpdateAuthor: true,
showLastUpdateTime: true,
versions: {
current: {
label: 'Next',
path: 'next',
},
},
},
blog: {
showReadingTime: true,
editUrl: 'https://github.com/org/project/edit/main/docs/',
},
theme: {
customCss: require.resolve('./src/css/custom.css'),
},
},
],
],
themeConfig: {
navbar: {
title: 'Project',
logo: {
alt: 'Project Logo',
src: 'img/logo.svg',
},
items: [
{ type: 'doc', docId: 'intro', position: 'left', label: 'Docs' },
{ to: '/blog', label: 'Blog', position: 'left' },
{ type: 'docsVersionDropdown', position: 'right' },
{ href: 'https://github.com/org/project', label: 'GitHub', position: 'right' },
],
},
footer: {
style: 'dark',
links: [
{
title: 'Docs',
items: [{ label: 'Getting Started', to: '/docs/intro' }],
},
{
title: 'Community',
items: [{ label: 'Discord', href: 'https://discord.gg/xxx' }],
},
],
copyright: `Copyright ยฉ ${new Date().getFullYear()} Organization.`,
},
prism: {
theme: require('prism-react-renderer/themes/github'),
darkTheme: require('prism-react-renderer/themes/dracula'),
additionalLanguages: ['csharp', 'powershell', 'bash'],
},
algolia: {
appId: 'YOUR_APP_ID',
apiKey: 'YOUR_SEARCH_API_KEY',
indexName: 'project',
},
},
};
module.exports = config;
# mkdocs.yml
site_name: Project Documentation
site_url: https://docs.example.com
repo_url: https://github.com/org/project
repo_name: org/project
edit_uri: edit/main/docs/
theme:
name: material
palette:
- scheme: default
primary: indigo
accent: indigo
toggle:
icon: material/brightness-7
name: Switch to dark mode
- scheme: slate
primary: indigo
accent: indigo
toggle:
icon: material/brightness-4
name: Switch to light mode
features:
- navigation.instant
- navigation.tracking
- navigation.tabs
- navigation.sections
- navigation.expand
- navigation.indexes
- toc.follow
- content.code.copy
- content.code.annotate
- search.suggest
- search.highlight
plugins:
- search
- git-revision-date-localized:
enable_creation_date: true
- minify:
minify_html: true
- mike:
version_selector: true
css_dir: css
javascript_dir: js
markdown_extensions:
- pymdownx.highlight:
anchor_linenums: true
- pymdownx.superfences:
custom_fences:
- name: mermaid
class: mermaid
format: !!python/name:pymdownx.superfences.fence_code_format
- pymdownx.tabbed:
alternate_style: true
- admonition
- pymdownx.details
- attr_list
- md_in_html
- toc:
permalink: true
nav:
- Home: index.md
- Getting Started:
- Installation: getting-started/installation.md
- Configuration: getting-started/configuration.md
- User Guide:
- Features: user-guide/features.md
- Reference:
- API: reference/api.md
- About:
- Changelog: about/changelog.md
extra:
version:
provider: mike
social:
- icon: fontawesome/brands/github
link: https://github.com/org/project
# .github/workflows/docs.yml
name: Documentation
on:
push:
branches: [main]
paths:
- 'docs/**'
- '.github/workflows/docs.yml'
pull_request:
branches: [main]
paths:
- 'docs/**'
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: docs/package-lock.json
- name: Install dependencies
working-directory: docs
run: npm ci
- name: Lint Markdown
run: npx markdownlint-cli2 "docs/**/*.md"
- name: Check links
working-directory: docs
run: npm run check-links
build:
runs-on: ubuntu-latest
needs: lint
steps:
- uses: actions/checkout@v5
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: docs/package-lock.json
- name: Install dependencies
working-directory: docs
run: npm ci
- name: Build
working-directory: docs
run: npm run build
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: docs/build
deploy:
if: github.ref == 'refs/heads/main'
needs: build
runs-on: ubuntu-latest
permissions:
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
preview:
if: github.event_name == 'pull_request'
needs: build
runs-on: ubuntu-latest
steps:
- name: Deploy preview
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: docs/build
destination_dir: pr-preview/${{ github.event.number }}
- name: Comment preview URL
uses: actions/github-script@v7
with:
script: |
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: '๐ Documentation preview: https://${{ github.repository_owner }}.github.io/${{ github.event.repository.name }}/pr-preview/${{ github.event.number }}/'
})
# azure-pipelines.yml
trigger:
branches:
include:
- main
paths:
include:
- docs/**
pool:
vmImage: 'ubuntu-latest'
variables:
pythonVersion: '3.11'
stages:
- stage: Validate
jobs:
- job: Lint
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '$(pythonVersion)'
- script: |
pip install -r docs/requirements.txt
pip install markdownlint-cli2
displayName: 'Install dependencies'
- script: markdownlint-cli2 "docs/**/*.md"
displayName: 'Lint Markdown'
- stage: Build
dependsOn: Validate
jobs:
- job: Build
steps:
- task: UsePythonVersion@0
inputs:
versionSpec: '$(pythonVersion)'
- script: pip install -r docs/requirements.txt
displayName: 'Install dependencies'
- script: mkdocs build --strict
displayName: 'Build documentation'
- publish: site
artifact: documentation
- stage: Deploy
dependsOn: Build
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
jobs:
- deployment: Deploy
environment: production
strategy:
runOnce:
deploy:
steps:
- download: current
artifact: documentation
- task: AzureStaticWebApp@0
inputs:
app_location: '$(Pipeline.Workspace)/documentation'
azure_static_web_apps_api_token: $(AZURE_STATIC_WEB_APPS_TOKEN)
// .markdownlint.json
{
"default": true,
"MD001": true,
"MD003": { "style": "atx" },
"MD004": { "style": "dash" },
"MD007": { "indent": 2 },
"MD009": true,
"MD010": true,
"MD012": true,
"MD013": { "line_length": 120, "code_blocks": false, "tables": false },
"MD022": { "lines_above": 1, "lines_below": 1 },
"MD024": { "siblings_only": true },
"MD025": { "front_matter_title": "" },
"MD026": { "punctuation": ".,;:!" },
"MD029": { "style": "ordered" },
"MD030": { "ul_single": 1, "ol_single": 1, "ul_multi": 1, "ol_multi": 1 },
"MD033": { "allowed_elements": ["details", "summary", "kbd", "br"] },
"MD035": { "style": "---" },
"MD036": false,
"MD040": true,
"MD041": true,
"MD046": { "style": "fenced" },
"MD048": { "style": "backtick" }
}
# .vale.ini
StylesPath = styles
MinAlertLevel = suggestion
Packages = Microsoft, write-good, proselint
[*.md]
BasedOnStyles = Vale, Microsoft, write-good
# Ignore code blocks
BlockIgnores = (?s) *(`{3}.*?`{3})
# Custom rules
Microsoft.Contractions = NO
Microsoft.HeadingPunctuation = YES
write-good.Passive = YES
write-good.Weasel = YES
write-good.TooWordy = YES
// API Documentation Generation with XML Comments
/// <summary>
/// Manages user authentication and authorization.
/// </summary>
/// <remarks>
/// <para>
/// This service handles all authentication flows including:
/// <list type="bullet">
/// <item>Password-based authentication</item>
/// <item>OAuth 2.0 / OpenID Connect</item>
/// <item>API key authentication</item>
/// </list>
/// </para>
/// </remarks>
/// <example>
/// <code>
/// var result = await authService.AuthenticateAsync(credentials);
/// if (result.IsSuccess)
/// {
/// var token = result.Value.AccessToken;
/// }
/// </code>
/// </example>
public interface IAuthenticationService
{
/// <summary>
/// Authenticates a user with the provided credentials.
/// </summary>
/// <param name="credentials">The authentication credentials.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <returns>
/// A result containing the authentication response on success,
/// or an error on failure.
/// </returns>
/// <exception cref="AuthenticationException">
/// Thrown when authentication fails due to invalid credentials.
/// </exception>
Task<Result<AuthenticationResponse>> AuthenticateAsync(
AuthenticationCredentials credentials,
CancellationToken cancellationToken = default);
}
// Program.cs - Swagger/OpenAPI configuration
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo
{
Title = "Project API",
Version = "v1",
Description = "API documentation for the Project",
Contact = new OpenApiContact
{
Name = "API Support",
Email = "api@example.com",
Url = new Uri("https://docs.example.com")
},
License = new OpenApiLicense
{
Name = "MIT",
Url = new Uri("https://opensource.org/licenses/MIT")
}
});
// Include XML comments
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
options.IncludeXmlComments(xmlPath);
// Security definitions
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Description = "JWT Authorization header using the Bearer scheme.",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.Http,
Scheme = "bearer"
});
options.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
Array.Empty<string>()
}
});
});
// check-links.mjs
import { remark } from 'remark';
import remarkLintNoDeadUrls from 'remark-lint-no-dead-urls';
import { read } from 'to-vfile';
import { glob } from 'glob';
import { reporter } from 'vfile-reporter';
const files = await glob('docs/**/*.md');
for (const file of files) {
const result = await remark()
.use(remarkLintNoDeadUrls, {
skipLocalhost: true,
skipOffline: true,
})
.process(await read(file));
console.error(reporter(result));
}
// docs.spec.ts - Playwright screenshot tests
import { test, expect } from '@playwright/test';
test.describe('Documentation Screenshots', () => {
test('homepage renders correctly', async ({ page }) => {
await page.goto('/');
await expect(page).toHaveScreenshot('homepage.png');
});
test('API reference page', async ({ page }) => {
await page.goto('/docs/api/reference');
await expect(page.locator('.api-content')).toBeVisible();
await expect(page).toHaveScreenshot('api-reference.png');
});
test('dark mode toggle', async ({ page }) => {
await page.goto('/');
await page.click('[data-theme-toggle]');
await expect(page).toHaveScreenshot('homepage-dark.png');
});
});
| Practice | Description |
|---|---|
| Single Source of Truth | Each concept documented in one place |
| Progressive Disclosure | Start simple, link to details |
| Consistent Structure | Same sections across similar pages |
| Clear Navigation | Logical hierarchy, breadcrumbs |
| Search Optimization | Good headings, keywords, descriptions |
Documentation Versioning:
Option 1: Version Folders (Docusaurus/MkDocs mike)
โโโ docs/
โ โโโ version-1.0/
โ โโโ version-2.0/
โ โโโ current/
Option 2: Branch-based
โโโ main (current)
โโโ v1.x
โโโ v2.x
Option 3: Git Tags
โโโ v1.0.0
โโโ v2.0.0
โโโ latest
Recommendation: Use tool-native versioning (Docusaurus versioned_docs, mike for MkDocs)
When implementing docs-as-code:
For detailed guidance:
Last Updated: 2025-12-26