demarkus-library
Sub-project hub for demarkus-library — the web front-end ("Universe Library")
for a demarkus universe: a server-rendered Go + htmx reading room over a
broker-fronted knowledge system. Standalone repo latebit-io/demarkus-library,
own release cadence (mirrors obsidian-demarkus).
All durable knowledge about this project lives under /demarkus-library/. This
hub is the discovery backstop — keep it current.
Resuming? Start with Roadmap & Resume — how to run today, the file map, and the Phase 1b task breakdown (Fable 5 vs Opus).
Source of truth
- Plan — Universe Library — the authoritative plan (architecture, identity model, phases 0–5, build-model strategy, resolved decisions, open questions). Fetch this first in any new session.
Sections
- Roadmap & Resume — status, how to run, Phase 1b breakdown with Fable-5 tagging
- Architecture — app structure, transport, MCP-client/session model, render pipeline (TBD)
- Decisions (ADRs) — one file per decision at
adr/<NNNN>-<title>.md - Patterns — Go + htmx + goldmark idioms, conventions (TBD — doc not yet written)
- Debugging — bugs, gotchas, investigations (TBD)
- Debt — technical debt, deferred work (TBD)
- Journal — session notes, one file per day at
journal/<YYYY-MM-DD>.md- 2026-06-10 — Phase 0 + Phase 1a shipped & merged
Status
- Phase 0 — Foundation spike: DONE, merged to
main. A real demarkus doc renders server-side in a browser over the QUIC fetch client. - Phase 1a — Reading room (features-first): DONE, merged to
main(PR #2). Built over the current direct-QUIC world. Routes:/(default doc),/d/<path>(document, or the stacks listing when path ends in/),/search?q=(card catalog, LOOKUP, debounced htmx, click-through, real<form>so it works without JS),/versions/<path>(editions),/health. Link rewriting maps internal doc/dir/version links to in-app/d/<path>. htmx fragment-vs-page: targeted swaps return thecontentpartial, boosted nav + no-JS return the fullpage. x/net on v0.56.0 (CVE-patched), govulncheck clean. - Phase 1b — Library card (the turnstile): NEXT. Broker MCP-gateway outbound
adapter implementing
port.WorldGateway(+ org-scoped OAuth login, cookie session, tokens server-side) — swapped in at the composition root, core/web untouched. Task breakdown + Fable-5 tagging in the roadmap. This is where the open anonymous-reads question gets resolved. - Deferred: backlinks / "cited by" (no server verb — needs a graph crawl;
plan defers the viz); world directory / floor (multi-world from the
roothub).
Architecture — hexagonal (ports & adapters)
Dependencies point inward (adapters → ports → core); the core knows nothing of Echo, QUIC, or goldmark. See ADR 0002. Echo v5 + bulwarkauth idioms retained (ADR 0001).
cmd/demarkus-library/ composition root — wires adapters into the core
internal/core/
domain/ document.go entities + sentinel errors (no external deps)
port/ port.go inbound + outbound port interfaces (ReadingService; WorldGateway, Renderer)
service/ reading.go application core — Read/Browse/History/Search
internal/adapter/
inbound/web/ Echo handlers/routes/view + link rewriting (driving adapter)
outbound/world/ demarkus QUIC fetch (Fetch/List/Versions/Lookup) → port.WorldGateway
outbound/markdown/ goldmark + bluemonday → port.Renderer
replace directives point demarkus client/protocol at local ../demarkus.
.coderabbit.yaml encodes the dependency rule as per-path review instructions.
Front-end philosophy
SSR-first, htmx-hard, no JSON — see ADR 0003.
The server renders all HTML; htmx is the only interaction layer; no JSON API, no
client-side state. Realized in 1a: link rewriting + linkifyCatalogPaths keep
navigation server-driven; the page/content template split gives htmx fragments
without a duplicate render path; the search box is a real <form> (degrades
without JS). htmx is vendored (web/static/htmx.min.js, pinned to the latest
release — currently 2.0.10) and served from the binary — no CDN. JS islands are
a last resort, each tracked as a concession in ADR 0003.
Open questions
- Does the broker expose any anonymous-readable surface? Decides whether Phase 1b
hits the broker directly vs a dev world for unauthenticated reads. Resolve in 1b
by checking
mcp_auth.go/mcp_gateway.goin the broker source.
Stack (decided)
Server-rendered Go (Echo v5 + html/template + htmx), goldmark + bluemonday for markdown→sanitized HTML, MCP client over the broker MCP gateway (Phase 1b+), org-scoped OIDC (auth-code/PKCE/DCR), tokens server-side only. Single Go binary, no Node build. Go 1.26.4. Build on Opus 4.8 by default; Fable 5 as the escalation valve.
Phase 1b plan (2026-06-11)
- Phase 1b — Web SSO over the Broker — concrete two-repo plan (broker confidential web client → library redirect SSO + MCP gateway)
- ADR 0004 — Broker confidential web client + redirect SSO — reject device flow; keep broker/library separate
Open question (anonymous reads) is RESOLVED: /mcp is always bearer-gated —
login is a hard turnstile.
Multi-world floor + federation (2026-06-11)
The deferred "world directory / floor" backlog item is BUILT (branch
feature/world-floor): documents addressed as (world, path), routes
/w/<world>/..., mark:// links traverse worlds — knowledge-system names via
the broker, host[:port] via direct QUIC (DEMARKUS_FEDERATION, default on).
Read token never leaves the home host. The root hub is the floor: its world
links are clickable entrances. Details in journal 2026-06-11.
Currency note (2026-07-04): the Status/phases sections above are frozen history (Phase 1b era). The living status is the tail of Roadmap & Resume. ADRs now run through 0005 (spatial trail) · 0006 (interaction overlays) · 0007 (pane-scroll room — the default).