Stage 7 · Master
Developer Portal & Software Catalog
TechDocs: Documentation as Code
Integrate MkDocs, auto-generate API docs from OpenAPI, version docs with code, and surface in the portal.
TechDocs Overview
TechDocs is Backstage's documentation system: MkDocs-based, markdown-first, versioned with code, rendered in the portal. It solves 'docs rot' by making documentation part of the development workflow — not a separate Confluence space.
Architecture
- Source: Markdown files in repo (docs/ or mkdocs.yml at root)
- Build:
techdocs-cliormkdocs buildin CI (GitHub Actions, GitLab CI) - Output: Static HTML + assets uploaded to blob storage (S3, GCS, Azure Blob, MinIO)
- Serve: TechDocs backend proxies requests to blob storage (auth, permissions)
- Render: TechDocs frontend (iframe) in portal entity page
MkDocs Configuration
site_name: Payment Service Docs
site_description: Documentation for the Payment Service
site_url: https://github.com/myorg/payment-service
repo_url: https://github.com/myorg/payment-service
repo_name: myorg/payment-service
nav:
- Home: index.md
- Getting Started:
- Quickstart: getting-started/quickstart.md
- Configuration: getting-started/configuration.md
- API Reference: api-reference.md
- Architecture:
- Overview: architecture/overview.md
- Decisions: architecture/decisions.md
- Operations:
- Runbook: operations/runbook.md
- Alerts: operations/alerts.md
- Dashboards: operations/dashboards.md
theme:
name: material
palette:
- scheme: default
primary: indigo
accent: indigo
- scheme: slate
primary: indigo
accent: indigo
features:
- navigation.tabs
- navigation.sections
- navigation.expand
- search.highlight
- search.share
- content.code.copy
plugins:
- search
- techdocs-core
- gen-files:
scripts:
- docs/gen-api-reference.py
- literate-nav:
nav_file: SUMMARY.md
markdown_extensions:
- admonition
- codehilite
- pymdownx.details
- pymdownx.superfences
- pymdownx.tabbed:
alternate_style: true
- toc:
permalink: true
MkDocs Material theme with TechDocs plugins. Auto-generates API reference from OpenAPI via gen-files plugin.
API Documentation from OpenAPI
#!/usr/bin/env python3
"""Generate API reference markdown from OpenAPI spec."""
import yaml
from pathlib import Path
def generate_api_reference():
spec_path = Path("openapi.yaml")
if not spec_path.exists():
return
with open(spec_path) as f:
spec = yaml.safe_load(f)
output = ["# API Reference
", "Auto-generated from OpenAPI spec. Do not edit manually.
"]
for path, methods in spec.get("paths", {}).items():
output.append(f"## {path}
")
for method, details in methods.items():
output.append(f"### {method.upper()}
")
if details.get("summary"):
output.append(f"{details['summary']}
")
if details.get("description"):
output.append(f"{details['description']}
")
# Parameters, responses, etc.
output.append("
")
Path("docs/api-reference.md").write_text("
".join(output))
if __name__ == "__main__":
generate_api_reference()
Script runs in CI to generate API reference markdown from OpenAPI spec. Can use redocly or custom generator.
Versioning & CI
- Docs live in repo → versioned with code (git tags = doc versions)
- TechDocs backend serves docs for specific entity + version (via git ref)
- CI pipeline: lint markdown → build mkdocs → upload to blob storage → register in catalog
- Preview: PR builds deploy to preview URL (e.g.,
pr-123.docs.platform.example.com) - Retention: Keep last N versions, archive older to cold storage
name: TechDocs
on:
push:
branches: [main]
tags: ['v*']
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- name: Install dependencies
run: |
pip install mkdocs-material mkdocs-techdocs-core mkdocs-gen-files mkdocs-literate-nav pyyaml
- name: Generate API reference
run: python docs/gen-api-reference.py
- name: Build TechDocs
run: techdocs-cli generate --no-docker
- name: Upload to S3
if: github.event_name == 'push'
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
run: |
techdocs-cli publish --publisher-type awsS3 --storage-name ${{ secrets.TECHDOCS_BUCKET }} --entity ${{ github.repository }} --branch ${{ github.ref_name }}
- name: Deploy Preview
if: github.event_name == 'pull_request'
run: |
# Deploy to preview bucket with PR number prefix
techdocs-cli publish --publisher-type awsS3 --storage-name ${{ secrets.TECHDOCS_PREVIEW_BUCKET }} --entity ${{ github.repository }} --branch pr-${{ github.event.number }}
CI builds docs on every push/PR. Main branch + tags publish to production bucket; PRs to preview bucket.
Best Practices
- README.md at repo root → auto-linked in portal entity page
- mkdocs.yml at repo root → auto-discovered by TechDocs
- Runbook.md required for production services (enforced by scorecard)
- Architecture Decision Records (ADRs) in docs/architecture/decisions/
- Auto-generate API docs from OpenAPI — never write manually
- Link to docs from code:
// See: https://docs.platform.example.com/payment-service - Search: TechDocs search indexes all markdown — write for discoverability
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.