Maintaining the docs

How to change anything on this site and ship it. The whole loop is ~10 seconds, edit-to-live.

Where everything lives

WhatWhere
Markdown content (the pages you’re reading)apps/docs/src/routes/<section>/<slug>/+page.md
Sidebar nav structureapps/docs/src/lib/nav.ts
Page layout (sidebar, breadcrumb, header)apps/docs/src/routes/+layout.svelte
Visual styling (Rizoma palette)apps/docs/src/app.css
Landing pageapps/docs/src/routes/+page.svelte
Built output (committed to git)apps/docs/build/
Served from on the ops VM/opt/wiqaia-ops/docs/ (auto-extracted on push)

Preview locally

Run the SvelteKit dev server while editing. Hot reload — save the file, see it in the browser.

pnpm --filter @wiqaia/docs dev

Then open http://localhost:5180. Nothing leaves your machine.

Publish

Build, commit (both source and build/), push. The server’s post-receive hook does the rest.

pnpm --filter @wiqaia/docs build
git add apps/docs
git commit -m "docs: <what you changed>"
git push

Live within ~1 second of git push returning. No CI runner, no remote build, no IAP tunnel.

If you have make installed (not default on WSL):

make docs-publish

Runs the same three commands in sequence. The Makefile target also skips committing if build/ didn’t change, so you never get empty commits.

The whole flow, end-to-end

edit .md file                          ops VM
  │                                    ─────────
  pnpm build                           Gitea post-receive hook
  │  (5s, local)                          │
  │                                       │ extracts apps/docs/build/
  git commit                              │
  git push  ─────────────────────────────►│
  │  (HTTPS to git.rizoma.sa)             │
  │                                       │ writes to /opt/wiqaia-ops/docs/
  │                                       │
  done                                    Caddy serves it ► https://git.rizoma.sa/docs/

Adding a new page

  1. Create the file: apps/docs/src/routes/plan/my-new-page/+page.md (or wherever).
  2. Add an entry in apps/docs/src/lib/nav.ts so it shows in the sidebar.
  3. Build + commit + push.

The sidebar nav is rendered from nav.ts — one source of truth. Adding a page without updating nav.ts produces an unreachable URL.

mdsvex gotchas

The doc pages are processed by mdsvex, which turns markdown into Svelte components. Two things will break the build:

  • A bare < followed by a digit or space. mdsvex thinks it’s the start of a Svelte tag. Write < 30s instead of < 30s, or rewrap as “under 30s”.
  • Bare \{foo\} in prose. Treated as a Svelte template expression. Wrap in backticks: `{foo}`, or use {foo}. Inside fenced or inline code blocks, braces are safe as-is.

When something breaks

SymptomLikely cause
pnpm build fails with “Expected a valid element or component name”Bare < or {...} in markdown — see above
Push succeeds but site doesn’t updateThe hook didn’t fire. SSH into the VM, run sudo docker exec gitea bash -c 'echo "x x refs/heads/master" \| /data/git/repositories/rizoma/wiqaia.git/hooks/post-receive.d/01-deploy-docs' to invoke manually and see errors
Site loads but the nav doesn’t show your new pageYou forgot to add the entry in nav.ts
Page exists in nav.ts but 404sNo +page.md at the matching path
Tabs/spaces look weird, sidebar overlaps contentHard-refresh — Caddy doesn’t aggressively cache but your browser might

Why this architecture

We considered three options for “auto-deploy on push”:

  1. Gitea Actions — full CI runner on the VM. Builds SvelteKit during the workflow.
  2. Build locally + rsync via IAPgcloud compute ssh/scp tunnel for each deploy.
  3. Commit build/, server-side post-receive hook extracts it. ← what we use.

Option 1 was rejected because the ops VM is e2-small (2 GB RAM). A SvelteKit build peaks around 600-900 MB, and the VM’s also running Gitea + Caddy. OOM risk. Bumping to e2-medium would fix it but costs more.

Option 2 was tried briefly; every deploy paid 60-90s of IAP tunnel handshake overhead before the actual 1.9 MB transfer. Frustratingly slow for a docs site.

Option 3 has one ugly trade-off — built HTML lives in git history, which bloats over time. At this scale (~1.9 MB per build, infrequent edits), the bloat is irrelevant. In exchange we get: single git push, sub-second deploy, no extra infrastructure.

WiqAIa+ Docs · Rizoma