# Architecture Overview ```mermaid graph LR %% ── External ────────────────────────────────────────────────────────── NF([novelfire.net]) KK([Kokoro-FastAPI TTS]) LE([Let's Encrypt]) CL([Browser / iOS App]) %% ── Init containers ─────────────────────────────────────────────────── subgraph INIT["Init containers (one-shot)"] MI[minio-init\nmc: create buckets] PI[pb-init\nbootstrap collections] end %% ── Storage ─────────────────────────────────────────────────────────── subgraph STORAGE["Storage"] MN[(MinIO :9000\nchapters · audio\navatars · browse)] PB[(PocketBase :8090\nbooks · chapters_idx\naudio_cache · progress\nscrape_jobs · app_users · ranking)] VK[(Valkey :6379\npresign URL cache\nTTL-based · shared)] MS[(Meilisearch :7700\nindex: books)] end %% ── Application ─────────────────────────────────────────────────────── subgraph APP["Application"] CD["Caddy :443/:80\ncustom build + caddy-ratelimit\nauto-HTTPS · security headers\nrate limiting · error pages"] BE[Backend API :8080\nGo HTTP server] RN[Runner :9091\nGo background worker\n/metrics endpoint] UI[SvelteKit UI :3000\nadapter-node] end %% ── Ops ─────────────────────────────────────────────────────────────── subgraph OPS["Ops"] WT[Watchtower\npolls every 5 min\nautopull + redeploy\nbackend · runner · ui] end %% ── Init → Storage ──────────────────────────────────────────────────── MI -.->|create buckets| MN PI -.->|bootstrap schema| PB %% ── App → Storage ───────────────────────────────────────────────────── BE -->|blobs| MN BE -->|structured records| PB BE -->|cache presigned URLs| VK RN -->|chapter markdown & audio| MN RN -->|read/update jobs & books| PB RN -->|index books on scrape| MS UI -->|read presign cache| VK UI -->|auth · progress · comments| PB %% ── App internal ────────────────────────────────────────────────────── UI -->|"REST API (server-side)\n/api/catalogue /api/book-preview\n/api/chapter-text /api/audio"| BE %% ── Caddy routing ───────────────────────────────────────────────────── CD -->|"/* catch-all\n/api/scrape/*\n/api/chapter-text-preview/*\n→ SvelteKit (auth enforced)"| UI CD -->|"/health /scrape*\n/api/browse /api/book-preview/*\n/api/chapter-text/*\n/api/reindex/* /api/cover/*\n/api/audio-proxy/*"| BE CD -->|/avatars/* presigned GETs| MN %% ── Runner → External ───────────────────────────────────────────────── RN -->|scrape HTTP GET| NF RN -->|TTS HTTP POST| KK CD -->|ACME certificate| LE %% ── Ops ─────────────────────────────────────────────────────────────── WT -->|watch label-enabled| BE WT -->|watch label-enabled| RN WT -->|watch label-enabled| UI %% ── Client ──────────────────────────────────────────────────────────── CL -->|HTTPS :443 single entry| CD ```