docs-as-code

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Docs-as-Code Skill

Docs-as-Code Skill

When to Use This Skill

何时使用该Skill

Use this skill when:
  • Docs As Code tasks - Working on documentation pipeline automation and docs-as-code workflows
  • Planning or design - Need guidance on Docs As Code approaches
  • Best practices - Want to follow established patterns and standards
在以下场景使用该Skill:
  • Docs As Code 任务 - 处理文档流水线自动化与 Docs-as-Code 工作流相关工作
  • 规划或设计阶段 - 需要 Docs As Code 方法的指导
  • 最佳实践参考 - 希望遵循已确立的模式和标准

Overview

概述

Implement documentation-as-code workflows with automated pipelines, version control, and CI/CD integration.
通过自动化流水线、版本控制和CI/CD集成,实现文档即代码工作流。

MANDATORY: Documentation-First Approach

强制要求:文档优先方法

Before implementing docs-as-code:
  1. Invoke
    docs-management
    skill
    for documentation patterns
  2. Verify tooling versions via MCP servers (context7 for docusaurus/mkdocs)
  3. Base guidance on current best practices
在实施Docs-as-Code之前:
  1. 调用
    docs-management
    skill
    获取文档模式指导
  2. 通过MCP服务器验证工具版本(context7用于docusaurus/mkdocs)
  3. 基于当前最佳实践制定指导方案

Docs-as-Code Philosophy

Docs-as-Code 理念

text
Docs-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                                       │
└─────────────────────────────────────────────────────────────────────────────┘
text
Docs-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                                       │
└─────────────────────────────────────────────────────────────────────────────┘

Documentation Tooling Comparison

文档工具对比

ToolLanguageBest ForBuild Speed
DocusaurusJS/ReactProduct docs, versioningFast
MkDocsPythonTechnical docs, Material themeFast
SphinxPythonAPI docs, reStructuredTextMedium
HugoGoLarge sites, speedVery Fast
AstroJSModern sites, MDXFast
VitePressJS/VueVue ecosystemVery Fast
JekyllRubyGitHub Pages nativeMedium
工具语言适用场景构建速度
DocusaurusJS/React产品文档、版本管理快速
MkDocsPython技术文档、Material主题快速
SphinxPythonAPI文档、reStructuredText中等
HugoGo大型站点、追求速度极快
AstroJS现代站点、MDX快速
VitePressJS/VueVue生态极快
JekyllRubyGitHub Pages原生支持中等

Project Structure

项目结构

Docusaurus Structure

Docusaurus 结构

text
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/
text
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/

MkDocs Structure

MkDocs 结构

text
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
text
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

Configuration Templates

配置模板

Docusaurus Configuration

Docusaurus 配置

javascript
// 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;
javascript
// 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 Configuration

MkDocs 配置

yaml
undefined
yaml
undefined

mkdocs.yml

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
undefined
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
undefined

CI/CD Pipeline Templates

CI/CD 流水线模板

GitHub Actions for Docusaurus

GitHub Actions 用于 Docusaurus

yaml
undefined
yaml
undefined

.github/workflows/docs.yml

.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 }}/'
        })
undefined
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 }}/'
        })
undefined

Azure DevOps for MkDocs

Azure DevOps 用于 MkDocs

yaml
undefined
yaml
undefined

azure-pipelines.yml

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)
undefined
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)
undefined

Documentation Linting

文档检查

Markdownlint Configuration

Markdownlint 配置

json
// .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" }
}
json
// .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 Configuration

Vale 配置

yaml
undefined
yaml
undefined

.vale.ini

.vale.ini

StylesPath = styles
MinAlertLevel = suggestion
Packages = Microsoft, write-good, proselint
[*.md] BasedOnStyles = Vale, Microsoft, write-good
StylesPath = styles
MinAlertLevel = suggestion
Packages = Microsoft, write-good, proselint
[*.md] BasedOnStyles = Vale, Microsoft, write-good

Ignore code blocks

Ignore code blocks

BlockIgnores = (?s) *(
{3}.*?
{3})
BlockIgnores = (?s) *(
{3}.*?
{3})

Custom rules

Custom rules

Microsoft.Contractions = NO Microsoft.HeadingPunctuation = YES write-good.Passive = YES write-good.Weasel = YES write-good.TooWordy = YES
undefined
Microsoft.Contractions = NO Microsoft.HeadingPunctuation = YES write-good.Passive = YES write-good.Weasel = YES write-good.TooWordy = YES
undefined

Living Documentation

活文档

Generating API Docs from Code

从代码生成API文档

csharp
// 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);
}
csharp
// 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);
}

OpenAPI Documentation Generation

OpenAPI 文档生成

csharp
// 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>()
        }
    });
});
csharp
// 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>()
        }
    });
});

Documentation Testing

文档测试

Link Checking

链接检查

javascript
// 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));
}
javascript
// 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));
}

Screenshot Testing

截图测试

typescript
// 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');
  });
});
typescript
// 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');
  });
});

Best Practices

最佳实践

Content Organization

内容组织

PracticeDescription
Single Source of TruthEach concept documented in one place
Progressive DisclosureStart simple, link to details
Consistent StructureSame sections across similar pages
Clear NavigationLogical hierarchy, breadcrumbs
Search OptimizationGood headings, keywords, descriptions
实践说明
单一事实来源每个概念仅在一处文档中说明
渐进式披露从简单内容开始,链接到详细说明
一致的结构相似页面使用相同的章节结构
清晰的导航逻辑化层级结构,面包屑导航
搜索优化合理的标题、关键词和描述

Writing Guidelines

写作指南

  1. Use active voice: "Configure the setting" not "The setting should be configured"
  2. Be concise: Remove unnecessary words
  3. Use examples: Show, don't just tell
  4. Maintain consistency: Same terms throughout
  5. Update regularly: Documentation rots quickly
  1. 使用主动语态:比如用"配置该设置"而非"该设置应被配置"
  2. 保持简洁:删除不必要的词汇
  3. 使用示例:演示而非仅描述
  4. 保持一致性:全程使用相同术语
  5. 定期更新:文档会快速过时

Versioning Strategy

版本控制策略

text
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)
text
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)

Workflow

工作流

When implementing docs-as-code:
  1. Choose Tooling: Select SSG based on team skills and requirements
  2. Set Up Structure: Create organized folder hierarchy
  3. Configure CI/CD: Automated builds, previews, deployments
  4. Add Linting: Markdown linting, link checking, spell check
  5. Enable Reviews: PR-based workflow with tech writer review
  6. Deploy Versioning: Set up version management strategy
  7. Monitor Analytics: Track usage, search queries, gaps
实施Docs-as-Code时的步骤:
  1. 选择工具:根据团队技能和需求选择静态站点生成器
  2. 设置结构:创建有序的文件夹层级
  3. 配置CI/CD:自动化构建、预览和部署
  4. 添加检查:Markdown检查、链接验证、拼写检查
  5. 启用审核:基于PR的工作流,包含技术作者审核
  6. 部署版本控制:设置版本管理策略
  7. 监控分析:跟踪使用情况、搜索查询和内容缺口

References

参考资料

For detailed guidance:

Last Updated: 2025-12-26
如需详细指导:

最后更新: 2025-12-26