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.