Skip to content

synnet-devhub (this docs hub)

Synced read-only from /home/synnet/synnet-devhub/README.md. Edit at the source, not here.

Internal-only developer documentation hub. One place to browse, per module, its README, CLAUDE.md, ROADMAP, and docs/ — synced read-only from every SYNNET repo. Served on the LAN with Caddy tls internal. Containerized and migratable: move the container, re-point the mounts, update internal DNS.

  • Built with Astro + Starlight (static, fast, built-in Pagefind search).
  • Manifest-driven: register every module in modules.json only.
  • Content is synced read-only from source repos — edit at the source, never here.
  • Auto-rebuilds when any watched source changes.

bin/sync.mjs reads modules.json and assembles a Starlight content tree under src/content/docs/modules/<category>/<id>/, pulling each module’s README.md (overview), CLAUDE.md, ROADMAP, docs/, and optional adr/ / runbooks/. Markdown without frontmatter gets a title injected (Starlight requires one) plus a source-attribution note. The sidebar (src/generated/sidebar.json) is generated from the manifest and consumed by astro.config.mjs.

In production, a builder container syncs + builds the static site into a shared volume and watches sources for changes; caddy serves that volume over the LAN.

Terminal window
pnpm install
pnpm dev # sync + Starlight dev server (live reload; no search index)
# or:
pnpm build && pnpm preview # full static build incl. Pagefind search

Point modules.json source paths at real repos on your machine (or run with a test manifest: MODULES_FILE=modules.dev.json pnpm build).

Quick start — internal server (production)

Section titled “Quick start — internal server (production)”
  1. Edit infra/compose.yaml volume mounts so each repo is mounted read-only at the /repos/... path used in modules.json.
  2. Point internal DNS so synvirt.mx resolves to this host on the LAN (split horizon). DevHub serves the /dev path; never expose it publicly.
  3. Bring it up and trust the internal CA on your machines/browsers:
Terminal window
cd infra
docker compose up -d --build
# trust Caddy's internal root CA (so https://synvirt.mx/dev has no warning):
docker compose cp caddy:/data/caddy/pki/authorities/local/root.crt /tmp/synnet-devhub-ca.crt
sudo cp /tmp/synnet-devhub-ca.crt /usr/local/share/ca-certificates/synnet-devhub-ca.crt
sudo update-ca-certificates

(Or use the Taskfile.yml targets: task up, task trust-ca.)

{
"categories": [
{ "id": "synvirt", "label": "SynVirt — Product" }
],
"modules": [
{
"id": "synvirt-core", // url + folder id (unique)
"title": "synvirt (core daemon)",
"category": "synvirt", // must match a category id
"source": "/repos/synvirt", // container path (mounted read-only)
"readme": "README.md", // optional, default README.md -> overview
"claude": "CLAUDE.md", // optional -> claude page
"roadmap": "docs-internal/roadmap.md", // optional -> roadmap page
"docsDir": "docs", // optional -> docs/ subtree
"adrDir": "docs-internal/adr", // optional
"runbooksDir": "runbooks" // optional
}
]
}
  1. Mount its repo read-only in infra/compose.yaml (e.g. /srv/foo:/repos/foo:ro).
  2. Add an entry to modules.json pointing source at /repos/foo.
  3. The builder rebuilds automatically (or run pnpm build locally).
  • Internal only. No public ACME, no Cloudflare. Caddy tls internal per SYNNET internal-services policy.
  • Migratable. State is just: the container image, modules.json, and the mounted repos. To move hosts: copy the project, re-point mounts, update DNS.
  • Path vs subdomain. This ships under synvirt.mx/dev (Astro base: /dev). Internal DNS for synvirt.mx must point at this host on the LAN; the Caddyfile serves /dev/* from the built site and can optionally proxy the rest to the public platform ingress. Mind split-horizon routing against the public site.
  • English for all UI, code, commits, logs and docs.