Skip to content

Unified SPOT Documentation Site

Design record of 2026-04-16. The plan for the one documentation site. It was first built in a documentation repository; the site is now built from this repository (mkdocs.yml). Internal host names are replaced by placeholders. It lists no security finding.

Context

SPOT documentation is scattered across 3 MkDocs sites (core, sdk, deploy) hosted on separate GitLab Pages URLs, plus READMEs in ~10 plugin repos that have no generated docs. Users must jump between sites with no shared search or navigation. We want a single unified site at one URL.

Approach

Use mkdocs-multirepo-plugin in a new documentation repo. At build time the plugin git-clones each SPOT repo (sparse checkout), extracts their docs/ folder, and merges everything into one MkDocs Material site. Docs stay in their source repos. No git submodules.

New repository: documentation

Files to create

documentation/
  mkdocs.yml              # Root config with !import directives
  docs/
    index.md              # Landing page (project overview, quick links)
    assets/
      logo.png            # SPOT logo (copy from core)
  .gitlab-ci.yml          # Pages build + triggered by child repos
  requirements.txt        # mkdocs + plugins pinned versions

mkdocs.yml structure

site_name: SPOT Documentation
site_url: https://<gitlab-pages-host>/spot/docs
repo_url: https://<gitlab-host>/spot/docs

theme:
  name: material
  palette:
    - scheme: default
      primary: red
      toggle: { icon: material/brightness-7, name: Dark mode }
    - scheme: slate
      primary: red
      toggle: { icon: material/brightness-4, name: Light mode }
  features:
    - navigation.tabs
    - navigation.sections
    - navigation.expand
    - navigation.instant
    - navigation.top
    - search.suggest
    - search.highlight
    - content.code.copy

plugins:
  - search
  - multirepo:
      cleanup: true
      keep_docs_dir: true
  - minify: { minify_html: true }

# Standard markdown extensions (same set as core today)
markdown_extensions:
  - admonition
  - pymdownx.details
  - pymdownx.superfences:
      custom_fences:
        - name: mermaid
          class: mermaid
          format: !!python/name:pymdownx.superfences.fence_code_format
  - pymdownx.tabbed: { alternate_style: true }
  - pymdownx.highlight: { anchor_linenums: true }
  - pymdownx.inlinehilite
  - attr_list
  - md_in_html
  - tables
  - toc: { permalink: true }

nav:
  - Home: index.md
  - Platform: '!import https://<gitlab-host>/spot/core?branch=main&docs_dir=docs'
  - SDK: '!import https://<gitlab-host>/spot/sdk?branch=main&docs_dir=docs'
  - Deployment: '!import https://<gitlab-host>/spot/deploy?branch=main&docs_dir=docs'

What changes in child repos

Each of the 3 repos with existing MkDocs sites (core, sdk, deploy) already has a mkdocs.yml with a nav section. The plugin reads their nav to build the sub-navigation. No changes needed in child repos for basic functionality.

One optional improvement: add a downstream pipeline trigger to each child repo so the unified site rebuilds when docs change:

# Appended to each child repo's .gitlab-ci.yml
trigger-docs:
  stage: deploy
  trigger:
    project: spot/documentation
    branch: main
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
      changes:
        - docs/**/*
        - mkdocs.yml
        - "*.md"

Plugin repos (analyzers, providers, web-dashboard)

These repos have only a README.md and no docs/ directory or mkdocs.yml. They are NOT imported via !import. Instead, the unified site's landing page (docs/index.md) links to their GitLab README pages, or we add a small "Plugins" section with hand-written summaries in documentation/docs/plugins/.

If we later want to include them: add a minimal mkdocs.yml + docs/ directory to each plugin repo and add an !import line.

GitLab CI (.gitlab-ci.yml)

image: python:3.11-slim

before_script:
  - pip install -r requirements.txt

pages:
  stage: deploy
  script:
    - mkdocs build --strict --site-dir public
  artifacts:
    paths: [public]
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
    - if: $CI_PIPELINE_SOURCE == "pipeline"   # triggered by child repos
  environment:
    name: documentation
    url: https://<gitlab-pages-host>/spot/docs

The GitlabCIJobToken env var is automatically available in CI and the multirepo plugin uses it to clone private repos. No extra token management needed.

requirements.txt

mkdocs==1.6.*
mkdocs-material==9.*
mkdocs-multirepo-plugin==0.8.*
mkdocs-minify-plugin==0.8.*
pymdown-extensions==10.*

Implementation steps

  1. Create documentation repo on GitLab (spot/documentation)
  2. Create mkdocs.yml, docs/index.md, .gitlab-ci.yml, requirements.txt
  3. Write docs/index.md landing page with project overview and quick-links to each section
  4. Test locally: pip install -r requirements.txt && mkdocs serve (requires GitLab token: export GIT_TOKEN=glpat-...)
  5. Push and verify GitLab Pages builds successfully
  6. Add downstream trigger jobs to core, sdk, deploy repos
  7. Verify the unified site at the Pages URL
  8. Optionally: add a docs/plugins/ section summarising each analyzer/provider with links to their GitLab READMEs

Verification

  • mkdocs build --strict passes with zero warnings
  • All 3 imported repos' pages render correctly
  • Search works across all sections
  • Navigation tabs show Platform / SDK / Deployment
  • Mermaid diagrams render (architecture overview)
  • Links between sections work (cross-repo references)
  • GitLab Pages URL is accessible
  • Downstream trigger from core rebuilds the docs site

What stays unchanged

  • Each repo keeps its own docs/ and mkdocs.yml
  • Each repo can still build its own standalone docs site
  • No git submodules
  • No changes to existing content or nav structure