Composite documentation sections
Some product families span multiple Git repositories but should read as one area on the published site. The docs portal supports this with composite sections: federated ownership, centralized publishing.
Problem
The default portal model maps one registry entry → one workflow repository → one mirror folder → one navbar section. That works for standalone workflows like Superbuild, but not for ecosystems such as A2C, where:
a2c-workflowowns core method and engine documentationa2c-pre-commit-hooksowns hook package documentationa2c-vscode-extensionowns extension documentation
Copying sibling docs into a2c-workflow would violate ownership and create duplication. Separate top-level navbar tabs would fragment the reader experience.
Chosen model
| Principle | Implementation |
|---|---|
| Single published entry point | One Docusaurus plugin and navbar item (/a2c/) |
| Distributed ownership | Each repo authors docs in its own docs/ tree |
| Build-time aggregation | Portal sync mirrors each contributor into a subfolder of docs-a2c/ |
| Unified navigation | Registry sidebar_composition groups mirrored pages by contributor category |
| Source identity preserved | Docusaurus editUrl routes maintainers to the correct upstream repository |
┌─ a2c-workflow ─────────────┐ ┌─ a2c-pre-commit-hooks ────┐ ┌─ a2c-vscode-extension ──┐
│ docs/ (core) │ │ docs/ (hooks) │ │ docs/ (extension) │
│ sync_id: a2c │ │ sync_id: a2c-pre-commit… │ │ sync_id: a2c-vscode-ext…│
└──────────────┬──────────────┘ └─────────────┬──────────── ──┘ └────────────┬────────────┘
│ │ │
└───────────────────────────────┼──────────────────────────────┘
▼
┌────── docs-portal /a2c/ ──────┐
│ intro.md (portal-owned) │
│ workflow/… (core mirror) │
│ pre-commit-hooks/… │
│ vscode-extension/… │
└────────────────────────────────┘
Registry contract
Composite sections set section_type: composite in workflows/registry.yaml:
| Field | Purpose |
|---|---|
contributors[] | Upstream repos, each with sync_id, gitlab_project, target_subdir |
sidebar_composition[] | Sidebar blocks: portal intro doc + category per contributor |
target_dir, sidebar_file, … | Same as single-repo sections (one mirror root, one sidebar file) |
Each contributor repository ships docs/workflow-manifest.yaml with:
sync_id— matches registry contributor (used by CIWORKFLOW_SYNC_ID)section_id— parent composite section (a2c)sidebar_order— slugs within that contributor's mirror subfolder
Legacy manifests may still use workflow_id when it equals the core contributor sync_id.
Sync behaviour
python scripts/sync_workflow.py <sync_id>syncs one contributor and rebuilds the full composite sidebar (loading sibling manifests from local clones or CI fetch).python scripts/sync_all_workflows.pyexpands composite sections into all contributors.- Core contributor (
target_subdir: "") prunes stale files atdocs-a2c/root but never deletes sibling contributor subfolders. - Contributor subfolders (
pre-commit-hooks/,vscode-extension/) prune independently.
CI-generated companion assets
Some contributors build documentation assets in CI without committing them to git (for example ExTester UI screenshots). Declare ci_artifact_overlay in the contributor manifest:
ci_artifact_overlay:
job_name: test:integration:screenshots
required_in_ci: true
paths:
- docs/assets/extension/
- docs/extension-screenshots.md
The upstream pipeline forwards WORKFLOW_SYNC_PARENT_PIPELINE_ID and WORKFLOW_SYNC_ARTIFACT_JOB to docs-portal. Sync downloads the job artifact archive, overlays the clone, then mirrors markdown and companion_dirs into the portal repo so npm run build includes the PNGs.
Automated commits use chore(sync): Update mirrored docs for a2c (<sync_id>).
Onboarding a new A2C contributor
- Add docs + manifest in the new repository (
templates/workflow-manifest-contributor.yaml). - Add
docs/portal-integration.mdanddocs/navigation-meta.md. - Enable
workflow-docs:contract+trigger:docs-portalin that repo's CI with a uniqueWORKFLOW_SYNC_ID. - Register a new
contributors[]entry andsidebar_compositioncategory inworkflows/registry.yaml. - Run first sync from
docs-portaland verifynpm run build.
When to use composite vs standalone section
| Use composite | Use standalone section |
|---|---|
| Repos are facets of one product family readers expect together | Repo is an independent workflow product (e.g. Superbuild) |
| Docs cross-reference heavily within the family | Minimal cross-navigation with siblings |
| Separate navbar tab would confuse discovery | Distinct audience and lifecycle |
Related documents
- Sync architecture — mirror model and tooling
- Content ownership — edit boundaries
- Workflow onboarding — single-repo and contributor paths