Skip to content

Architecture

High-level shape of the system, written for someone trying to figure out where to look in the source.

Two halves, one binary

Backend is Go standard-library HTTP under server/. No framework. The HTTP handlers, providers, storage, auth, and Tailscale node all live here.

Frontend is Svelte 5 with runes ($state / $derived / $effect), Vite, TypeScript, Tailwind under web/. No SvelteKit. Theme + state stores live in *.svelte.ts files.

Vite builds the SPA into server/embedded/. Go's //go:embed pulls that directory into the binary at compile time. Result: one executable, no separate frontend deployment, no Node at runtime.

What's in this section

Page Topic
Server & SPA The build pipeline, the middleware chain, how the SPA reaches the API.
Storage & encryption Per-file encryption, the OS-keyring key, the cryptostore abstraction.
Authentication WebAuthn passkey flow, per-RPID grace, bearer-token CLI auth, the middleware chain.
Providers The Provider and ImageProvider interfaces; how OpenAIProvider / AnthropicProvider / A1111Provider / ComfyProvider plug in.
System prompt assembly How assembleMessages() turns a card + persona + history into the outbound message list, with marker substitution and SillyTavern preset support.

For the data layout on disk, see Reference → Data directory layout.

What's not here yet

The plugin axis (smelt-7bq) — hashicorp/go-plugin with in-process built-ins, per-axis protobuf contract — is decided but not yet wired. Today's "providers" are hardcoded Go implementations in the binary. When the plugin axis lands, the same Provider interface stays at the call site; only the registration mechanism changes.