Skip to content

Latest commit

 

History

History
29 lines (15 loc) · 1.83 KB

File metadata and controls

29 lines (15 loc) · 1.83 KB

Design Decisions

ZIM is truth; indexes are derived

Archives are the authoritative content source. SQLite FTS and vector rows are disposable representations. Per-archive lexical search retains a bounded native-ZIM fallback only for a missing index; all-library search remains indexed-only. Rebuilding or deleting an index does not mutate an archive.

SQLite only

One local SQLite file provides FTS5, popularity, and vector storage without a separate database service. The optional index.backend: sqlite setting is accepted for compatibility.

Instance-scoped runtime

cmd.App owns configuration and input/output streams for one invocation. main owns signal creation and one exit translation. Configuration uses a fresh loader per app so tests and concurrent invocations cannot leak Viper state.

Consumer-owned services

The library service owns configured-root path resolution. The indexer and search packages own narrow interfaces at their consumption boundaries. Archive handles are cached and synchronized by the archive manager. Domain packages do not depend on CLI or web presentation packages.

One web server

The standard-library server hosts the embedded Svelte SPA and JSON API. serve is canonical; ui is a deprecated alias. Request-local archive selection replaces mutable active-archive state.

Untrusted article documents

Downloaded archive HTML is not application UI. It is served as a separate document with restrictive CSP and loaded by a sandboxed iframe. Validated rewriting keeps internal navigation and resources on the selected same-origin archive routes.

Generated frontend contract

The compiled Svelte bundle is committed at internal/webui/dist, embedded into the Go binary, and regenerated from web/ using npm ci && npm run build. Go builds and tests therefore work from a clean archive without Node.