Lesson 3: TechDocs Architecture & Phase 7 Hands-On Lab Solutions
This module details Spotify Backstage's TechDocs (Docs-Like-Code) publishing pipeline and provides complete solutions for the Phase 7 Job-Essential Exercises.
π TechDocs Architecture: The Docs-Like-Code Philosophy
Traditional enterprise documentation fails because it lives in static wikis (Confluence, Notion) disconnected from source code. When developers refactor an API, they forget to update the wiki, and documentation rots.
TechDocs enforces Docs-Like-Code:
1. Documentation lives as Markdown inside a /docs directory inside the service's own Git repository.
2. Every time a Pull Request merges to main, a CI/CD job compiles the markdown using mkdocs and uploads the static HTML bundle to an enterprise AWS S3 bucket.
3. Backstage fetches and displays the documentation natively inside the component's catalog page. Documentation stays synchronized with every code commit!
sequenceDiagram
autonumber
actor Dev as π©βπ» Developer (Edits docs/api.md)
participant Git as π GitHub Enterprise
participant CI as π€ GitHub Actions (TechDocs Builder)
participant S3 as πͺ£ AWS S3 (TechDocs Storage)
participant BS as π₯οΈ Spotify Backstage UI
Dev->>Git: git push origin main
Git->>CI: Triggers .github/workflows/techdocs.yml
CI->>CI: techdocs-cli generate (Runs MkDocs build)
CI->>S3: techdocs-cli publish (Uploads to s3://corp-techdocs/default/component/orders/)
Dev->>BS: Opens "Docs" tab on Order Service
BS->>S3: Fetches HTML bundle
BS-->>Dev: Renders interactive TechDocs with search! β
π οΈ Lab 1: The Catalog Definition Challenge
Objective
Author an enterprise catalog-info.yaml declaring an OrderManagementService Component that exposes an OrderAPI, depends on an external CustomerDatabase Resource, and binds to an on-call team.
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
name: order-management-service
description: "Processes customer orders and manages payment transitions"
annotations:
github.com/project-slug: "corp/order-management"
backstage.io/techdocs-ref: "dir:."
pagerduty.com/integration-key: "pd-order-mgmt-key"
datadog.com/service-name: "order-management"
spec:
type: service
lifecycle: production
owner: group:checkout-squad
system: ecommerce-core
providesApis:
- order-api-v1
dependsOn:
- resource:default/customer-postgres-db
---
apiVersion: backstage.io/v1alpha1
kind: API
metadata:
name: order-api-v1
description: "REST API for order creation and status checks"
spec:
type: openapi
lifecycle: production
owner: group:checkout-squad
system: ecommerce-core
definition: |
openapi: "3.0.0"
info:
title: Order API
version: "1.0.0"
paths:
/orders:
get:
summary: List orders
responses:
'200':
description: OK
---
apiVersion: backstage.io/v1alpha1
kind: Resource
metadata:
name: customer-postgres-db
description: "AWS RDS PostgreSQL Multi-AZ Cluster"
spec:
type: database
owner: group:platform-team
system: ecommerce-core
π οΈ Lab 2: The Golden Path Scaffolder Challenge
Objective
Create an end-to-end Backstage Software Template (template.yaml) that prompts for a project name, renders a skeleton repository, creates a private GitHub repository, and commits an initial GitOps ArgoCD manifest.
apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
name: python-microservice-template
title: Production-Ready Python Service
description: "Scaffold a Python service with Dockerfile, CI, and ArgoCD registration"
spec:
owner: group:platform-team
type: service
parameters:
- title: Microservice Metadata
required: [app_name, owner_group]
properties:
app_name:
type: string
title: Service Identifier
description: Lowercase alphanumeric name (e.g. inventory-service)
owner_group:
type: string
title: Owning Squad
ui:field: OwnerPicker
steps:
- id: template
name: Render Template Files
action: fetch:template
input:
url: ./skeleton
values:
app_name: ${{ parameters.app_name }}
owner: ${{ parameters.owner_group }}
- id: publish
name: Publish to GitHub
action: publish:github
input:
allowedHosts: ['github.com']
description: 'Provisioned via Platform Golden Path'
repoUrl: github.com?owner=my-enterprise-org&repo=${{ parameters.app_name }}
defaultBranch: main
repoVisibility: private
- id: register
name: Register in Backstage Catalog
action: catalog:register
input:
repoContentsUrl: ${{ steps.publish.output.repoContentsUrl }}
catalogInfoPath: '/catalog-info.yaml'
π οΈ Lab 3: The TechDocs Integration Challenge
Objective
Configure a microservice repository with a mkdocs.yml file and GitHub Actions workflow to build and publish TechDocs to an AWS S3 bucket.
1. mkdocs.yml in Microservice Root
site_name: Order Management Service Documentation
plugins:
- techdocs-core
nav:
- Overview: index.md
- Architecture: architecture.md
- API Reference: api.md
2. .github/workflows/techdocs.yml
name: Publish TechDocs to S3
on:
push:
branches: [main]
paths:
- 'docs/**'
- 'mkdocs.yml'
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 18 }
- uses: actions/setup-python@v5
with: { python-version: '3.11' }
- name: Install TechDocs CLI & MkDocs
run: |
pip install mkdocs-techdocs-core
npm install -g @techdocs/cli
- name: Generate TechDocs Static Site
run: techdocs-cli generate --no-docker
- name: Configure AWS Credentials via OIDC
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/TechDocsPublisherRole
aws-region: us-east-1
- name: Publish to S3 Bucket
run: |
techdocs-cli publish \
--publisher-type awsS3 \
--storage-name corp-backstage-techdocs-storage \
--entity default/Component/order-management-service