Start the unified local UI with:
zim serve simple-wikiThe default address is http://localhost:8080; configuration can change the host, port, and timeouts. zim ui simple-wiki remains available as a deprecated alias.
The library selector is filesystem-authoritative: it lists .zim archives beneath the configured library and marks whether each has a SQLite index and how many indexed articles it contains. The server fetches those statuses in batches instead of issuing one SQLite query per archive. The startup archive remains selected even when it lives outside that root.
Lexical search uses SQLite when an index exists and falls back to bounded native ZIM title search only when that archive has no index. Other SQLite failures remain visible. Semantic search requires semantic vectors and returns an explicit error when they are missing.
The server reuses one SQLite store for default search and library-status requests. It initializes its local, cache-disabled Model2Vec embedder only when the first semantic request arrives, so text-only sessions do not pay model startup cost.
Article routes remain /article/{url}. The SPA requests article metadata without reading the body, then loads the document once through its URL in a sandboxed iframe. Archive links, images, styles, fonts, and media are rewritten through validated same-origin routes while the selected library is preserved. Scripts, forms, plugins, connections, frames, and remote resources are blocked by the document CSP.
The SPA shell is revalidated on each navigation. Its content-hashed files under /_app/immutable/ use a one-year immutable cache policy. Raw archive resources use strong ETags derived from immutable ZIM metadata; matching wildcard, weak, or comma-list If-None-Match requests return 304 without opening the body.
Compatibility URLs continue to work:
/search?q=termredirects to the SPA with the same query./raw/{path}redirects to/api/raw/{path}.
Press Ctrl+C for graceful shutdown.