fogserv.cloud Architecture Overview
Status: Active
Last Updated: 2026-08-26
Category: fogserv - Project Reference
Prerequisites: ../frontend/tanstack.md, ../databases/prisma-connections.md
Time: 30 min read
Tags: fogserv, architecture, tanstack-start, prisma, sqlite, k3s, bun, react19
Summary
How the fogserv.cloud codebase is put together: a TanStack Start (React 19 + Vite) SSR site with all server logic centralized in src/server/api.ts, a Prisma + SQLite data layer, Bun as the runtime and package manager, shipped as a single container image (ghcr.io/fogserv/fogserv-cloud) to a k3s cluster behind Caddy ingress.
Context / Why This Matters
This is the map for everything else in this section: before touching code, deploying, or debugging, know which layer owns which responsibility. The repo lives at git.shire.one/fogserv/website; generic patterns are covered by the linked KB sections, while this article records only what's true of this stack.
Implementation / Core Content
Stack at a glance
| Layer | Choice | Where |
|---|---|---|
| Runtime / package manager | Bun 1 | Dockerfile, bun.lock |
| Framework | TanStack Start (SSR) + React 19 | app.config.ts, src/routes/ |
| Styling | Tailwind CSS v4 + PostCSS | postcss.config.js, tailwind.config.ts |
| Data | Prisma ORM → SQLite | prisma/schema.prisma, DATABASE_URL |
| Server logic | Single module src/server/api.ts |
auth, posts CRUD, email, webhooks |
| Mailgun send + signed webhook ingestion | src/server/api.ts |
|
| CI/CD | GitHub Actions → GHCR → cluster | .github/workflows/, Enterprise/apps/ |
| Hosting | k3s Deployment + Caddy ingress | Enterprise/apps/fogserv-cloud.yaml |
Request flow
browser ──► Caddy ingress (TLS) ──► Service :80 ──► pod :8080 (bun preview, SSR)
│
├─ src/routes/*.tsx (UI)
├─ src/server/api.ts (auth/CMS/email logic)
└─ Prisma ── SQLite (file DB)
Key directories
src/routes/— file-based routing;kb_.$.tsxsplat route renders KB markdown,admin*.tsxis CMS UIsrc/server/api.ts— all server-side logic was extracted here out ofvite.config.ts; treat it as the backend boundaryprisma/schema.prisma— User, Post, Tag, Subscription, EmailCampaign models; SQLite providerEnterprise/— cluster provisioning (core/: k3s, Caddy, Longhorn, Flux, Postgres, Forgejo) and app manifests (apps/fogserv-cloud.yaml)kb/— this knowledge base; glob-imported into the site at build time (see kb-browser)
Build & run pipeline
bun install --frozen-lockfilebunx prisma generatebun run build— Vite build + prerender; KB markdown loaded viaimport.meta.glob('/kb/**/*.md', { query: '?raw' })- Production image runs
bun run preview --host 0.0.0.0 --port 8080
Note vite.ssr.external: ['@prisma/client'] in app.config.ts — Prisma must stay external to SSR bundling or the generated client breaks at runtime.
Security posture (already hardened)
- Auth-gated email sending; register/login/logout/verify flows in
api.ts - Mailgun webhooks fail closed without
MAILGUN_WEBHOOK_SIGNING_KEYsignature verification - Per-IP rate limiting on sensitive endpoints
- Secrets never in Git — dotenvx locally (../sysadmin/secrets.md), on-cluster Secret
fogserv-cloud-secretsin production
Practical Examples
"Where do I add an API endpoint?" — src/server/api.ts. Keep route components thin; anything touching Prisma, email, or secrets belongs there.
"Where does content come from?" — Blog/changelog posts live in SQLite via the CMS; KB articles are static markdown under kb/, compiled in at build time. Changing KB content requires an image rebuild + redeploy, not just an edit.
Common Pitfalls & Troubleshooting
- Editing
vite.config.tsserver logic — it was deliberately emptied intosrc/server/api.ts; don't reintroduce logic there. - Prisma bundled into SSR output — breaks cryptically; keep the
ssr.externalentry intact. - Assuming Postgres — production is SQLite-on-PVC (deployment-runbook); Postgres exists in the cluster for other workloads.
- Expecting hot-reload of KB content — it's build-time static; rebuild to ship article changes.
Next Steps / Ops Actions
- Deploying or debugging the running site: deployment-runbook
- How
/kb/markdown reaches the browser: kb-browser
Sources & Related Articles
- Repo:
git.shire.one/fogserv/website· Go-live guide: repodocs/DEPLOYMENT.md· State handoff: repoHANDOFF.md - Related: ../frontend/tanstack.md, ../databases/prisma-connections.md, ../databases/sqlite-production-patterns.md, ../cicd/gitops-pipelines.md
Change Log
2026-08-26
- Initial creation from HANDOFF.md, app manifests, and source inspection