The deployed app is a single SvelteKit 2 / Svelte 5 process on adapter-node. State lives in per-room JSONL files; the browser talks to a room page, a form action and three small JSON/SSE routes.
Runtime layers
| Layer | Implementation | Note |
|---|---|---|
| Edge | nginx TLS vhost for chat.loca.zone, proxy to loopback | Owned with the app deployment; see [[operations |
| Server | node build/index.js from @sveltejs/adapter-node, chat.service | Hardened system-scope unit, runs as the loca user |
| Storage | DATA_DIR/rooms/<slug>/events.jsonl plus room.json per room | No database, no migrations; rollback is a file copy |
| Client | Svelte 5 runes ($state, $derived), keyed block list | Component-local state; display name kept in localStorage |
Routes
| Route | Method | Purpose |
|---|---|---|
/ | GET, form action POST | Room list and create-room form; title Chat · loca.zone |
/r/<room> | GET | Chat page with server-rendered history; title <Room title> · Chat |
/api/status | GET | { assistant: { configured, model }, rooms } |
/api/rooms/<room>/messages | GET | Room history from the JSONL log |
/api/rooms/<room>/messages | POST | { author, content }, content at most 8000 characters, answers 201 and fans out |
/api/rooms/<room>/events | GET (SSE) | Live stream; replays from ?after=<ms> or Last-Event-ID |
Room slugs derive from the title and match ^[a-z0-9][a-z0-9-]{0,31}$. There is no room-list API and no room baked into the code; rooms are public to anyone holding the link.
Backend boundary
- Rooms are real and multi-user: every browser on the same room sees appended messages through SSE. There is no authentication and no identity guarantee; display names are self-declared.
- The assistant is optional, never mocked. It is driven by an OpenAI-compatible upstream selected through environment variables (see Assistant environment). On this host no key-free model exists, so the deployment ships with the assistant unconfigured:
/api/statusreportsassistant.configured=false, a message starting with@aiyields asystemmessage stating that no model is configured, and the UI shows a standing “Assistant offline” notice. - No third-party services are called unless the upstream is configured.
Render pipeline
message text → splitBlocks(src, streaming) → renderBlock() per block → keyed {#each} → sanitized {@html}| Piece | What it guarantees | Source |
|---|---|---|
blocks.ts splitBlocks | Closed blocks get content-hash ids and never re-key; the growing tail keeps a fixed tail / tail-code key; fences close only on a CommonMark closer, never on the last line while streaming | Research proof, replayed char-by-char in seven cases with zero closed-id churn |
render.ts renderBlock | marked (GFM, breaks: true so single newlines become line breaks, a chat-specific deviation from the proof) then isomorphic-dompurify with a forbidden-tag list and no data attributes | Bare dompurify throws during SSR; the isomorphic build is required |
| SvelteKit CSP | script-src 'self' with Kit nonces, img-src 'self' data: blob: | Sanitizing alone does not stop image-load exfiltration; the CSP does |
Stable keys are not render caching: a block still re-renders when its own content changes. The 124.6× figure in Research counts block renders on a 590-character document, not wall-clock time.
Wired versus evaluated
| Capability | Deployed | Evidence |
|---|---|---|
| Multi-user rooms, history, SSE fan-out | yes | live routes above |
| Streaming-safe Markdown blocks, sanitizer, CSP | yes | carried over from the research proof |
| OpenAI-compatible assistant | code present, not configured | /api/status |
Virtualized message list (virtua) | no | evaluated only |
Voice: STT, TTS, VAD (speaches, kokoro-js, vad-web) | no | evaluated only |
Math (katex), rich highlighting (shiki), diagrams (mermaid) | no | evaluated only |
| Offline / PWA / resumable streams | no | evaluated only |
| Auth, accounts, moderation | no | not implemented; treat identity as unverified |
Runtime dependencies are limited to marked and isomorphic-dompurify; the rest of the research stack stays a recommendation in Research.