Skip to content

docs.kevinryan.io

The documentation site at docs.kevinryan.io hosts all platform documentation, Architecture Decision Records, SDD specifications, and provenance documents. It is built with Astro Starlight and served by nginx.

TechnologyVersionRole
Astro^5Static site generator
@astrojs/starlight^0.34Documentation theme
Mermaid^11.12.3Diagram rendering
astro-mermaid^1Astro integration for Mermaid
sharp^0.33Image optimisation
graph TD
    subgraph sources["Content Sources"]
        docs["docs/<br/>(repo root)"]
        sdd[".sdd/<br/>(specs + provenance)"]
    end

    subgraph site["Astro Starlight"]
        symlink["src/content/docs/<br/>(symlink → docs/)"]
        config["astro.config.mjs<br/>(sidebar, integrations)"]
        footer["Footer.astro<br/>(custom component)"]
        css["custom.css<br/>(brand theme)"]
    end

    subgraph output["Build Output"]
        dist["dist/<br/>(static HTML)"]
    end

    docs --> symlink
    sdd -->|"symlinked via<br/>docs/specs, docs/provenance"| symlink
    symlink --> dist
    config --> dist

The docs site pulls content from multiple locations in the monorepo via symlinks:

docs/ # Repo root (canonical location)
├── index.md # Platform overview (home page)
├── ci-cd.md # GitHub Actions Workflows
├── cloudflare.md # Cloudflare DNS & CDN
├── docker-builds.md # Docker Builds
├── flux-cd.md # Flux CD Deployment
├── k3s.md # K3s Architecture
├── observability.md # Observability
├── terraform.md # Terraform Infrastructure
├── traefik.md # Traefik Ingress
├── umami.md # Umami Analytics
├── sites/ # Site Architectures
│ └── <site>.md
├── adr/ # Architecture Decision Records
│ └── adr-001 through adr-019
├── specs → ../.sdd/specification # SDD specifications (symlink)
└── provenance → ../.sdd/provenance # Spec provenance (symlink)

The key symlink chain:

  1. sites/docs-kevinryan-io/src/content/docs/../../../../docs/ (content lives at repo root)
  2. docs/specs../.sdd/specification (SDD specs pulled in)
  3. docs/provenance../.sdd/provenance (provenance docs pulled in)

This means documentation is editable from the repo root (docs/) and automatically appears in the built site. SDD specifications and provenance are maintained in .sdd/ and surfaced in the docs without duplication.

SettingValue
Site URLhttps://docs.kevinryan.io
TitleKevin Ryan — Docs
Integrationsastro-mermaid, Starlight
Custom CSS./src/styles/custom.css
Custom componentsFooter (commit SHA display)
AnalyticsUmami script injected via head config

The sidebar is manually configured with a mix of direct links and auto-generated sections:

  • Direct links for platform documentation pages
  • autogenerate for ADR, specs, and provenance directories (auto-discovers new .md files)

Uses Starlight’s docsLoader() and docsSchema() to define a single docs content collection covering all markdown files under src/content/docs/.

The site uses a custom dark theme that overrides Starlight defaults:

ElementValue
Accent colour#A8E10C (brand green)
Display fontBebas Neue
Body fontArchivo
Code fontJetBrains Mono
ThemeDark only (light theme selector hidden)

A custom Astro component that replaces Starlight’s default footer. It displays the PUBLIC_COMMIT_SHA environment variable, linking each page to the exact commit that produced it.

The site uses a multi-stage Docker build with special handling for symlinks:

  1. Build stage — Node.js 22 Alpine with pnpm:

    • Copies docs/ and .sdd/ from the monorepo root
    • Copies the site source
    • Replaces the src/content/docs symlink with real content via cp -rL (Docker COPY does not follow symlinks pointing outside the copied tree)
    • Runs astro build producing dist/
  2. Serve stage — nginx 1.28.2 Alpine serves the static output on port 8080

  • JSON structured access logs
  • Gzip compression
  • Long-lived cache for static assets (.css, .js, .svg, .png, .ico, .woff2)
  • No-cache for HTML
  • /healthz endpoint for Kubernetes probes
  • Security headers
  • try_files fallback to /404.html