Wiki engine spike — 2026-05-15

Constraints

  • Markdown-on-disk is hard. Raw .md files must live as real filesystem files so local AI agents (LeafWiki, Claude Code, grep, rg) can read them without a running server. Engines that store content only in a relational DB are rejected immediately.
  • Web UI required. Humans need a browser-based reading and editing surface with search, internal linking, and navigation. Static-site-generators with no web editor are second-class (acceptable only if they win on everything else).
  • Self-hostable on free/cheap infra. Target: Cloudflare Pages, Render free, or Koyeb free. Engines that require Postgres + Redis + S3 are operationally expensive even if free-tier hosts exist.
  • Low maintenance. No long-running containers with multiple required sidecars; no "still in alpha since 2022" projects.
  • No DB-only storage. BookStack (MySQL HTML blob), Outline (Postgres + S3), Wiki.js 2.x (Postgres with optional Git sync that is not the source of truth) — all rejected on this point alone.
  • Bonus (not required). Native HTTP/REST API or MCP connector for AI agents. We can build a thin pass-through wrapper if absent.

Candidates

Eliminated at the storage constraint

Engine Storage model Verdict
BookStack MySQL/MariaDB — content stored as HTML with markdown preserved in a separate column Reject: DB-only, no raw .md files
Outline Postgres primary store; Markdown is an export format, not the source of truth Reject: DB-only, requires Postgres + Redis + S3
Wiki.js 2.x Postgres with optional Git sync, but Git is a replica not the live store Reject: DB-only; v3.0 still in alpha since 2022, no committed release date
Logseq / Obsidian Publish Local-first graph DB (Logseq) / vendor-hosted static (Obsidian Publish) Reject: Logseq has no web-edit surface for teams; Obsidian Publish is a paid vendor host with no self-host option
Foam VSCode extension, no web server at all Reject: no web UI
Markwhen Timeline DSL, not a general wiki Reject: wrong tool entirely

Shortlisted

LeafWiki Quartz 4 MkDocs + Material Gollum Docusaurus 3
Storage Markdown on disk (./data/), SQLite for metadata/sessions only Pure markdown on disk (Obsidian-compatible) Pure markdown on disk Pure markdown on disk (Git repo) Pure markdown on disk
Auth Built-in: JWT sessions, roles (admin/editor/viewer), optional public read-only, optional --disable-auth None — static site, no auth layer None — static site No built-in auth; CAS SSO via external server None — static site
Editing UX Web editor (live preview, Ctrl+V image paste, keyboard-first) Git push only; no web editor Git push only; no web editor Web editor + git commits, or local editor Git push only; no web editor
Search Built-in full-text (title + body), runs in-process, no external dependency Client-side (Flexsearch), built into generated static HTML Client-side (lunr / built-in), no backend needed Built-in (Gollum server handles it) Algolia DocSearch or local Pagefind
Markdown flavor CommonMark + tables, task lists, footnotes, Mermaid, embedded audio/video, sanitized inline HTML Obsidian-flavour + wikilinks, backlinks, callouts, LaTeX, transclusions Python-Markdown + Material admonitions, tabs, diagrams (Mermaid), footnotes Kramdown + multiple other formats MDX (Markdown + React components)
Deployment cost Any VPS/Raspberry Pi, single binary or Docker; no Cloudflare Workers support (stateful server) Cloudflare Pages, Vercel, Netlify, GitHub Pages — free Cloudflare Pages, GitHub Pages, Netlify — free (static output) Any Ruby rack host; not suitable for Cloudflare Cloudflare Pages, Netlify, Vercel — free (static output)
Latest release v0.9.2 — 2026-05-05 v4.0.8 — 2024-08-21 9.7.6 — 2026-03-19 (maintenance mode since Nov 2025; critical fixes through Nov 2026) v6.1.0 — 2024-12-23 3.9 — April 2026
API for agents No REST API documented N/A (static files) N/A (static files) No REST API; filesystem is the API No REST API; filesystem is the API
Dealbreakers Cannot run on Cloudflare Pages (stateful); no OAuth/SSO; no REST API No web editor — agents can read files, humans cannot edit in browser In maintenance mode; no web editor; build pipeline required for every edit Ruby runtime; heavier than needed; auth model is primitive MDX is complex; build step required per edit; docs-site UX, not a wiki

LeafWiki (detail)

Single Go binary, v0.9.2 shipped 2026-05-05 with revision history, link refactoring, optimistic locking, and permalinks. Markdown files live in a configurable ./data/ directory as plain .md files — an AI agent can grep/Read them without the server running. SQLite holds only sessions, user roles, and metadata, not content. Full-text search is in-process (no Algolia/Meilisearch). Web editor with live preview and image upload. No REST API documented; no OAuth/SSO (local users only). Cannot run on Cloudflare Workers — it is a stateful TCP server. Must run on a VPS or container host.

Quartz 4 (detail)

Excellent static publishing of an Obsidian vault. Markdown + wikilinks + backlinks + graph view. Deploys to Cloudflare Pages for free. Active enough (v4.0.8, Aug 2024). The hard gap: no web editor. Humans must git push to update content. Acceptable for a read-heavy reference wiki where the team is comfortable with Git, but rules it out as the primary editing surface for non-dev stakeholders.

MkDocs + Material (detail)

Mature, battle-tested, all Insiders features now open-source (9.7.0). Client-side search, Mermaid, admonitions, tabs. Static output deploys to Cloudflare Pages. Dealbreakers for our use: maintenance mode as of November 2025 (feature-frozen, security patches only through Nov 2026), no web editor, build-step-per-edit friction.

Gollum (detail)

GitHub's own wiki engine. Git is the source of truth; web editor commits directly to the repo. Runs on any Ruby host. v6.1.0 Dec 2024 shows active maintenance. Problem: Ruby runtime is heavier than a Go binary, no first-class Docker image, auth story is "nothing or CAS SSO", and it will not run on Cloudflare Pages. It is a reasonable fallback if LeafWiki stalls.

Docusaurus 3 (detail)

Meta-backed, actively maintained (3.9, April 2026), Cloudflare Pages compatible. MDX lets you embed React. AI search via Algolia DocSearch v4. The model is docs-site-not-wiki: content is versioned alongside code, every edit requires a build, no web editor. Wrong UX model for a living knowledge base.


Recommendation

Use LeafWiki.

LeafWiki is the only shortlisted engine that satisfies every hard constraint simultaneously: Markdown files on disk readable by AI agents, a web editor for humans, built-in search with no external dependency, and a single-binary operational footprint requiring no Postgres/Redis/S3 sidecar. It is actively maintained (v0.9.2, 2026-05-05) with a solo maintainer who ships consistently. The two missing features — OAuth/SSO and a REST API — are real gaps but not blockers: the target audience is a small trusted team (built-in local users suffice for now), and a thin HTTP wrapper for AI agents can be added later since the raw .md files are always greppable on disk without any API.

The deployment constraint (cannot run on Cloudflare Pages) is a real tradeoff: LeafWiki needs a persistent TCP host. Render free tier (512 MB RAM, 0.1 vCPU, auto-sleep) or Koyeb free slot handle this. The Render free tier auto-sleeps after inactivity, which causes a cold-start latency on the first request — acceptable for an internal wiki. Koyeb's free slot is already occupied by the Typst compile service per topics/shared/koyeb.md, so Render is the first-choice host.


Storage path

Content already lives at wiki/content/ in the careervector-cvl repo. Confirm that location.

LeafWiki's --data-dir should point to wiki/content/ so the .md files it manages are the same files that git tracks. This means:

  • AI agents grep/Read from wiki/content/ directly (no server needed).
  • Humans edit via the LeafWiki web UI (server must be running, writes go to wiki/content/).
  • Git is the backup / version control layer; LeafWiki's own revision history is an additional safety net.
  • JobCache pages live under wiki/content/jobcache/ as a top-level namespace — JobCache is a peer project, not a child directory of CareerVector.

Do not create a separate repo for wiki content. The wiki is internal documentation for this codebase; co-locating it avoids the repo-sync problem and keeps git log coherent.


Deployment plan

Concern Decision
Host Render free tier (wiki-careervector service), Docker image ghcr.io/perber/leafwiki:latest, mounts wiki/content/ from a Render Disk ($1/mo, 1 GB) or volume
DNS wiki.careervector.corbet.ch → Render URL via Cloudflare CNAME (proxied); wiki.jobcache.corbet.ch → same service, different LeafWiki tree root or a subdirectory namespace
Auth LeafWiki built-in: one admin account, one editor account per project, public read-only (--public-access) for the careervector wiki; jobcache wiki private (no --public-access)
Single instance Run one LeafWiki process with --data-dir wiki/content/; use LeafWiki's tree structure to separate careervector/ and jobcache/ branches. Two separate services are overkill at this scale.
Backups Git commits from the Render service back to GitHub via a scheduled git push or CircleCI nightly job on corbet/unraid. LeafWiki's SQLite is disposable — only the .md files matter.

Seed pages

These five pages should be created on first boot, under wiki/content/:

  1. architecture-overview.md — The full-stack picture: SvelteKit front-end, Cloudflare Workers APIs, D1/R2/KV storage layers, Deno Deploy relay, and where CareerVector and JobCache share infrastructure versus run independently.
  2. vocabulary.md — Canonical definitions for domain terms (workspace, perspective, provider, job posting, snapshot, tenant) to prevent drift between code comments, UI copy, and agent prompts.
  3. operations-runbook.md — Step-by-step procedures for deploy, rollback, secrets rotation, Cloudflare quota checks, and incident triage; the on-call reference.
  4. testing-runbook.md — How to run the full test pyramid locally and in CI: unit → API → MCP tool → Playwright e2e; environment variables needed; known flaky tests and their bypass conditions.
  5. jobcache-careervector-relationship.md — Explicit description of what JobCache and CareerVector share (auth model, infra repo, wiki, Cloudflare account) versus what they own independently (DB schema, Workers, front-end, domain), with the rebrand-ready boundary documented.

Follow-up tasks

  • Provision Render service with LeafWiki Docker image and mount/volume pointing at wiki/content/
  • Configure DNS: wiki.careervector.corbet.ch and wiki.jobcache.corbet.ch CNAMEs in Cloudflare
  • Set admin password (write to secrets/leafwiki.md, do not commit plaintext)
  • Write the five seed pages listed above
  • Add a nightly CircleCI job on resource_class: corbet/unraid to git pull from the Render disk and commit any LeafWiki-originated edits back to the repo (keeps git and disk in sync)
  • Evaluate REST API need: if agents need programmatic write access, spike a thin Cloudflare Worker proxy that authenticates with a token and POSTs to LeafWiki's internal session-auth endpoints, or propose a PR upstream
  • Re-evaluate when LeafWiki adds OAuth/SSO (watching issue tracker); migrate auth if the team grows beyond ~5 users
Source: wiki/content/studies/wiki-engine-spike.md