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
| What | Where |
|---|---|
| Markdown content (the pages you’re reading) | apps/docs/src/routes/<section>/<slug>/+page.md |
| Sidebar nav structure | apps/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 page | apps/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
- Create the file:
apps/docs/src/routes/plan/my-new-page/+page.md(or wherever). - Add an entry in
apps/docs/src/lib/nav.tsso it shows in the sidebar. - 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< 30sinstead 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
| Symptom | Likely cause |
|---|---|
pnpm build fails with “Expected a valid element or component name” | Bare < or {...} in markdown — see above |
| Push succeeds but site doesn’t update | The 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 page | You forgot to add the entry in nav.ts |
Page exists in nav.ts but 404s | No +page.md at the matching path |
| Tabs/spaces look weird, sidebar overlaps content | Hard-refresh — Caddy doesn’t aggressively cache but your browser might |
Why this architecture
We considered three options for “auto-deploy on push”:
- Gitea Actions — full CI runner on the VM. Builds SvelteKit during the workflow.
- Build locally + rsync via IAP —
gcloud compute ssh/scptunnel for each deploy. - 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.