Skip to content

Maintain the documentation

The public documentation is built with Zensical from docs/ in this repository. zensical.toml defines audience-based navigation, the canonical URL, and theme settings. Existing document paths stay stable; navigation labels can change without moving files.

Preview and validate locally

Requirements: Python 3.11 or newer, Git, Bash, and a running Docker engine. The scripts use only the Python standard library. .github/docs-tools.env pins the shared tooling commit from hubuum/.github. That revision owns the digest-pinned official Zensical container, theme, checks, and reusable workflows. There is no Python package installation or virtual environment to maintain in this repository.

From the repository root:

bash scripts/docs.sh serve

Open http://127.0.0.1:8000. Stop the preview with Ctrl-C and rebuild after editing source files or configuration. Run the same validation as the publishing build with:

bash scripts/docs.sh check
bash scripts/docs.sh build
npx markdownlint-cli2 --config .markdownlint.json "**/*.md" "!target"

The build checks that every Markdown page has exactly one navigation entry, uses Zensical's strict internal-link and anchor validation, and checks the generated HTML links and assets against the GitHub Pages /hubuum/ prefix. The output is one edition in target/docs-site/; generated output and caches are ignored by Git. A local preview shows that edition; the version menu is populated when the edition is assembled with the published archive.

To build the original documentation from an older tag:

git fetch origin --tags
bash scripts/docs.sh build v0.0.16

The renderer stages the tagged docs/ content, filters navigation to pages that exist in that release, and adds any older pages to a release-reference section. For tags without a home page, it generates a short release entry point. It never copies current tutorials into an older release. Source links are pinned to the tag's resolved commit. The ordinary serve command previews the working tree.

Write for a reader's task

Section Reader's question Content to place here
Overview Is Hubuum relevant to us? Concepts, ecosystem, maturity, compatibility
Get started How do I reach a first success? Short, ordered tutorials with prerequisites and expected results
User guide How do I work with my data? Modeling, permissions, queries, data workflows
Administration How do I run and recover it? Deployment, configuration, identity, monitoring, runbooks
API & integrations How do I connect another system? HTTP contracts, client entry points, compatibility
Contributing How do I change Hubuum correctly? Development, architecture, verification, release policy

Keep tutorials distinct from exhaustive references. Explain prerequisites, required permissions, expected results, and failure recovery. Reuse a canonical reference with a relative link instead of copying its configuration tables into another guide. The same page can be linked from several audience landing pages while having one canonical navigation entry.

Use descriptive link labels, one H1 per page, a language on every code fence, and consistent Markdown table separators. Prefer normal Markdown; the home page uses a small HTML wrapper for Zensical's accessible card layout. The shared stylesheet adds only typography, color, and card treatment, and system fonts avoid a third-party font request.

When linking within docs/, use relative .md paths. For code or assets outside docs/, use an explicit GitHub blob/main/ or tree/main/ URL. Those files are not part of the static site. Keep generated references generated: use the OpenAPI, inventory, and operational-contract workflows.

Shared example dataset

Use the Atlas example for tutorials, client walkthroughs, screenshots, and product diagrams. Introduce the class before the object: Service/Atlas, Server/web-01, Location/Oslo, and Context/Research notes are the central examples. Keep class names and object names case-sensitive. Numeric IDs and revisions are runtime values, not fixture identities.

The canonical recipe is docs/assets/atlas/atlas.import.json. The neighboring backup is produced by the real server, never assembled by hand. Its manifest records checksums, sizes, counts, and the producing server version. Both files are published within each documentation edition, so release snapshots keep their original dataset. Client repositories should link to a matching server edition and reuse its files rather than maintaining independent seed data.

When showing complete object data in Markdown, put an atlas-data comment immediately before the JSON fence, for example <!-- atlas-data: object:Atlas -->. The offline check compares marked examples with the canonical import. Mark partial payloads and tutorial additions explicitly; do not label them as the unchanged baseline. Specialized contract examples may use placeholders or additional resources where Atlas does not cover the behavior.

Run from the repository root with Python 3.11+ and the production image built as described in development:

python3 tests/python/run.py unit tooling.test_atlas
python3 tests/python/run.py integration atlas check
python3 tests/python/run.py integration atlas verify --image hubuum-server:verify

After changing the import, regenerate the backup and manifest:

python3 tests/python/run.py integration atlas generate --image hubuum-server:verify

The generator and verifier reuse tests/python/integration/corpus.py's isolated Docker harness. They create their own network, databases, and temporary credentials; they do not accept an existing database URL. Generation publishes files only after import, application scenarios, and two restore rounds succeed. No third-party Python packages are required. For a regeneration check that leaves committed files untouched, add --directory target/generated-atlas-corpus.

CI checks metadata and documentation drift, imports and restores the committed corpus against the candidate production server, and regenerates into a temporary output directory. Changes to the dataset, its guide, or its tooling select the required checks. The larger functional corpus continues to cover scale and specialized edge cases.

GitHub Pages publishing

The intended public URL is https://hubuum.github.io/hubuum/. The root opens the latest published stable release, with immutable releases at /vX.Y.Z/ and an explicitly selected development edition at /main/. A version menu and banner identify the edition on every page. Search is scoped to the selected edition.

The Documentation workflow runs on pull requests, pushes to main, published releases, successful release-tag CI runs, and manual dispatch. The CI-completion trigger covers releases created with GITHUB_TOKEN, which do not trigger another release workflow. It accepts only successful tag pushes from this repository; pull-request CI runs cannot enter the publishing path. It uses the shared change classifier for ordinary changes. Release events and manual runs always build. It always resolves the Documentation check job, including when no build is needed, so that check can be required by branch protection.

Pull requests build development and latest-release editions and retain a documentation-site artifact for 14 days. Download and extract it, then run python3 -m http.server 8000 in its directory to review it. PRs have read-only repository permission and cannot publish Pages. After merge or a stable release publication, a separate serialized deployment job combines validated editions with the retained archive on the gh-pages branch, then uploads and deploys a Pages artifact. The archive is generated output, stored under site/ on that branch; source documentation remains on main and release tags. Deployment needs contents: write for the archive, pages: write, and id-token: write. No personal access token is needed.

Release directories are append-only. Rebuilding the same source commit retains the existing snapshot; a moved tag with a different commit is rejected. Updating main never modifies a release directory. The default is the highest published stable version in the archive, so backfilling an older tag does not move it backward. Prereleases do not publish or become the default.

One-time repository setup

A repository administrator must select Settings → Pages → Build and deployment → Source → GitHub Actions. Configure the github-pages environment to accept deployments from main and release tags matching v*. Add Documentation check to the repository's required checks if documentation builds should block merging.

The shared scripts/setup-pages.sh configures Pages for all six sites from an authenticated administrator's terminal.

After merging the setup, run the Documentation workflow on main if necessary to publish or retry the first deployment. The first publication includes the latest released tag even when that tag predates the website. Build validation works before Pages is enabled; publishing requires that repository setting.

Publish an older release

Open Actions → Documentation → Run workflow, select the main branch, and enter an existing stable release tag such as v0.0.15 in version. The workflow requires a published, non-draft, non-prerelease GitHub release for that tag. It builds the original tagged documentation with the current pinned renderer, retains all previously published versions, and adds the new version to the menu. Leave the input empty to refresh development and ensure the latest release is present. The selected root remains the latest release.

The archive lives independently of Actions artifact retention. Do not delete or force-push gh-pages: it retains the published release snapshots. A failed Pages deployment can be retried using a manual run; the archived snapshots remain unchanged.

For a custom domain, configure it in GitHub Pages and update site_url in zensical.toml to the actual canonical URL, then rebuild. The same static target/docs-site/ output can be uploaded to another static host. See GitHub's Pages workflow documentation for the hosting requirements.

Connecting companion projects

Organization landing page and project sites

The ecosystem entry point is https://hubuum.github.io/, published from a separate hubuum/hubuum.github.io repository. GitHub requires that repository name for an organization Pages site. This server repository publishes the project site at https://hubuum.github.io/hubuum/. Each companion repository can independently publish its own project site below the same host. See GitHub's site types.

Repository Responsibility Public entry point
hubuum/hubuum.github.io Ecosystem introduction, project cards, shared navigation, contribution and support links https://hubuum.github.io/
hubuum/hubuum Server concepts, tutorials, administration, HTTP contracts, and versioned references https://hubuum.github.io/hubuum/
Each client, CLI, or frontend repository Its own installation, examples, reference, compatibility, and releases https://hubuum.github.io/<repository>/
hubuum/.github GitHub organization profile and shared community files https://github.com/hubuum

The .github/profile/README.md file supplies the GitHub organization profile; it should introduce the ecosystem and link to the landing page. It does not control the root Pages site. See GitHub's organization-profile instructions.

The landing page contains an introduction, audience entry points, and five cards for Server, Frontend, CLI, Rust client, and Python client. Each card links to its documentation, source, and releases. All sites share typography, colors, ecosystem navigation, and a home link through pinned tooling in .github. Detailed content stays in the repository that owns it.

The ecosystem landing page has no combined product version. Each project owns its own release selector, and stable entry links open that project's latest released documentation. The server keeps /hubuum/vX.Y.Z/ and explicit /hubuum/main/ editions. Client and server releases need not have matching numbers. Link to existing companion guides until their sites are published; do not advertise an unprovisioned Pages URL as a working documentation link.

The organization-site repository and each companion site have their own Pages settings and publishing workflow. The server repository publishes /hubuum/; its deployments cannot overwrite the organization root or another project's site.

Content ownership and shared navigation

The server site links to the documentation maintained in the Rust client, Python client, CLI, and frontend repositories. It does not fetch another repository's moving default branch during a documentation build.

For each companion project, maintain these entry points in the ecosystem page and the interface guide:

  1. Repository and stable documentation home.
  2. Installation and first-use guide.
  3. Command, UI, or language API reference.
  4. Release notes and tested server compatibility, including evidence where available.
  5. A backlink to the shared server concepts, API contracts, and operations guides.

Each companion publishes its own Zensical site using shared tooling and its own navigation. This keeps independent releases independent and avoids copying examples into several repositories. The Python client retains its generated mkdocstrings API reference from the selected release's source.

If unified cross-project search becomes a requirement, introduce a reviewed manifest of pinned companion revisions and an explicit import step, preserving source/edit links and licenses. Do not silently aggregate main branches or claim compatibility based only on the fact that documentation builds together.

Changing the site tooling

Update the shared Zensical version and multi-architecture digest together, then build the site and check navigation, search, both color schemes, and narrow-screen layout. GitHub Actions are pinned to immutable commit SHAs.

Adopt shared changes by updating .github/docs-tools.env and both reusable workflow references to the same reviewed commit. The shared implementation and its tests are maintained in docs-tooling/ in hubuum/.github; each project pins its own adoption point.

When adding build inputs, update scripts/classify-ci-changes.sh and its regression tests so the documentation job runs for them. Do not suppress link validation to make a renamed heading or moved page pass; update the references.

Shared stylesheet fixes apply to retained release editions without re-rendering their content. Released HTML, downloads, scripts, and source revisions stay unchanged; only the shared presentation CSS is refreshed.