docs - Documentation Site
Purpose: VitePress documentation site for Swiss AI Hub. User-facing docs, arc42 ADRs, and auto-synced code deep dives. Automated EN→DE translation, auto-generated sidebar, GitHub Pages deployment.
Folder Structure
docs/
├── .vitepress/
│ ├── config.mts # Site config (locales, rewrites, sidebar, plugins)
│ ├── sidebar-logic.mjs # Auto-generates sidebar from folder structure
│ ├── components/ # GradientBackground.vue, NavigationBoxes.vue
│ └── theme/ # Layout.vue, custom.css (brand red, Outfit font)
├── docs/ # All documentation content
│ ├── 1_vision_and_positioning/
│ ├── 2_platform/
│ ├── 3_sdk/
│ ├── 4_ecosystem/
│ ├── 5_references/
│ └── 6_code_deep_dive/ # AUTO-SYNCED from package READMEs — NEVER edit
├── arc42/decisions/ # ADRs (YYYY_MM_DD_short-summary.md)
├── media/ # Images organized by topic (architecture/, sdk/, etc.)
├── public/ # Mostly GENERATED by generate-llm-files.mjs — NEVER edit the generated files
│ ├── CNAME # Static: GitHub Pages custom domain (committed, hand-edited)
│ └── robots.txt # Static: crawler rules (committed, hand-edited)
├── index.en.md # Homepage (English — source of truth)
├── index.de.md # Homepage (German — auto-generated)
├── sync-docs.sh # Syncs README files from monorepo packages
├── translate-docs.sh # EN→DE translation via LLM
├── translate-prompt.md # Translation system prompt and glossary
└── generate-llm-files.mjs # Generates LLM-optimized doc files in public/What NOT to Edit
Three categories of generated files — edits will be overwritten:
index.de.mdfiles: Overwritten bytranslate-docs.sh. Editindex.en.mdinstead.docs/6_code_deep_dive/: Overwritten bysync-docs.sh. Edit the sourceREADME.mdin each package.public/generated files:index.md,llms.txt,llms-full.txt,changelog.md,licenses.md, and thedocs/andde/subtrees are rebuilt bygenerate-llm-files.mjs— never edit these. The committed static filesCNAMEandrobots.txtare the exception: they are hand-edited and survive the generator (itscleanPublicDirectoryonly removes the generated paths). VitePress copies everything inpublic/to the deployed site root.
Page Structure
Every page lives in its own directory as index.en.md. Numbered folders control sidebar order:
docs/
├── 1_vision_and_positioning/ # First in sidebar
│ └── index.en.md
├── 2_platform/ # Second in sidebar
│ ├── index.en.md # Section overview
│ └── 1_getting_started/ # Nested page (ordered by prefix)
│ └── index.en.md- No
order:frontmatter — the numeric prefix in the directory name is the sole ordering mechanism - Sidebar is 100% auto-generated by
sidebar-logic.mjs— never manually configure it - Title derived from frontmatter
titlefield, or directory name if missing
Minimal frontmatter:
---
title: My Feature Title
description: Brief explanation (optional)
---Translation Pipeline
Automated English→German translation using gemini-2.5-flash via the llm CLI.
- Change detection: SHA-256 hash of
index.en.mdstored assource_shainindex.de.mdfrontmatter. If hashes match, translation is skipped. - Prompt rules: Defined in
translate-prompt.md— preserves code blocks, rewrites absolute links to/de/..., keeps technical terms, uses formal "Sie" German. - CI skips translation:
docs:build:cidoes not run translation. German files must be pre-committed to git. - Run:
pnpm run docs:translate(requirespipx install llm)
The source_sha field is load-bearing: if you manually edit index.de.md without changing the sha, the next translate run silently skips re-translation. Always re-run translation after editing English source.
Sync Pipeline
pnpm run docs:sync pulls README.md files from monorepo packages into docs/6_code_deep_dive/ as index.en.md. Deletes and rebuilds the entire 6_code_deep_dive/ content fresh each run. German .de.md copies are verbatim (no translation for synced READMEs). To update synced docs: edit the source README in the package, then re-run sync.
Commands
| Command | What it does |
|---|---|
pnpm run docs:dev | Dev server at localhost:5173 |
pnpm run docs:sync | Sync README files from monorepo |
pnpm run docs:translate | Generate German translations (requires llm CLI) |
pnpm run docs:build | Full build: sync + LLM files + translate + VitePress build |
pnpm run docs:build:ci | CI build: sync + LLM files + VitePress build (no translation) |
pnpm run docs:preview | Preview production build at localhost:4173 |
Writing Documentation
- Create
docs/N_section/M_topic/index.en.mdwithtitlefrontmatter - Run
pnpm run docs:translatefor German version - Preview:
pnpm run docs:dev - Commit both
.en.mdand.de.mdfiles
VitePress containers (used throughout):
::: tip
Helpful information.
:::
::: warning
Important caveat.
:::
::: details Click to expand
Collapsible content (JSON payloads, HTTP examples).
:::Images: reference with relative paths to media/ (../../../../media/architecture/high_level/tier_1.svg). Add data-zoomable attribute for lightbox behavior.
Architecture diagrams: the eight media/architecture/{high_level,low_level}/tier_*.svg files are rendered from media/architecture/architecture.drawio by pnpm run docs:render-diagrams (a Docker-based step that exports each drawio page using the page name as the output filename). Run it after editing the .drawio and commit the regenerated SVGs alongside the source.
Mermaid diagrams: inline fenced code blocks with mermaid language tag.
Custom Vue components available in any .md file: <NavigationBoxes />.
Media Organization
Images in topic-specific subdirectories under media/:
media/architecture/—.drawiosource files +.svgexports (high_level/,low_level/), regenerated viapnpm run docs:render-diagramsmedia/sdk/— tutorial screenshots and videosmedia/platform/— demo videosmedia/evaluation/,media/knowledge/,media/open_webui/— UI screenshots
Architecture diagrams (LikeC4)
The platform's C4 model lives in docs/likec4/ and is rendered as interactive web components in any docs page via <likec4-view view-id="...">. Source files:
docs/likec4/specification.c4— element kinds, colors, tagsdocs/likec4/model/*.c4— actors, containers, components, relationships (one file per C4 level)docs/likec4/views/*.c4— view definitions (one file per view family: context, containers, centered, dynamic, …)
The web component bundle is regenerated automatically by pnpm run docs:dev (prepended via likec4:codegen script). Output: docs/.vitepress/theme/likec4-webcomponent.js (gitignored). It's side-effect-imported in docs/.vitepress/theme/index.js; the Vue compiler is told likec4-* tags are custom elements in docs/.vitepress/config.mts.
When creating or editing views
Apply the design principles from the likec4-dsl skill, especially:
- Less per view, more views: target ≤10 boxes per view; split when over budget. For central containers (e.g. API Gateway) split inbound / outbound into separate views.
- Multiple parallel view families: tier views answer "what's in this layer?"; package-centered views answer "what does my package touch?"; dynamic views answer "how does scenario X flow?". Same model, different projections.
- Code-first for connectivity: when adding or editing edges, verify against source — READMEs and
docker-compose.ymlmiss runtime integrations (e.g. custom OpenWebUI pipelines, NATS RPC patterns). - Honest self-criticism: open the rendered diagram in the dev server before declaring a change done. If labels are squashed or edges tangled, fix it.
- Icons + tier colours: every container carries a tech/
bootstrap:icon and a tier colour (app = bbv red, data = slate, llm = secondary (renders blue), eventing = amber, identity/edge = indigo, observability = green, utility = gray, external = muted). See the skill's "Icons, colour, and relationship styling" section for the full convention. Note: the<likec4-view>webcomponent can't render a notation legend, so the encoding is conveyed by icons/colours/shapes themselves rather than an on-page key.
Connectivity research subagent
For deep-dive connectivity mapping of a single application container (packages/api, packages/agent, etc.), use the connectivity-researcher subagent (.claude/agents/connectivity-researcher.md). It reads code, not docker-compose, and returns structured edge inventories.
MCP server
The likec4 MCP server (.claude/mcp/mcp-likec4.sh) exposes the model for runtime introspection — read-project-summary, read-view, query-graph, find-relationship-paths. Useful for sanity-checking the model without re-reading the .c4 files.
ADRs
- Location:
arc42/decisions/ - Format:
YYYY_MM_DD_short-kebab-summary.md - Template:
arc42/decisions/0000_00_00_template.md(Context → Decision Drivers → Decision → Consequences) - See root CLAUDE.md for when to create an ADR
Theme & Branding
- Brand color: red (CSS variable overrides in
.vitepress/theme/custom.css) - Fonts: Outfit (text), JetBrains Mono (code)
- Dark mode: pure black background (
#000000) darkModeSelector: '.dark'— class-based dark mode
Deployment
- Automatic via GitHub Pages on release (
repository_dispatch: release-ready) - Manual:
workflow_dispatchon.github/workflows/deploy-docs.yml - Base path:
/(served from a custom domain;public/CNAMEholdsdocs.ai-hub.bbv.ch) - Live URL: https://docs.ai-hub.bbv.ch/
Essential Files
- VitePress config:
.vitepress/config.mts - Sidebar logic:
.vitepress/sidebar-logic.mjs - Custom theme:
.vitepress/theme/(Layout.vue,custom.css) - Translation script:
translate-docs.sh - Translation prompt:
translate-prompt.md - Sync script:
sync-docs.sh - LLM file generator:
generate-llm-files.mjs - ADR template:
arc42/decisions/0000_00_00_template.md - Deployment:
.github/workflows/deploy-docs.yml
