Skip to content
BoringStack
Star

Separation of concerns

2 min read

BoringStack splits the runtime into three layers. Each layer has one job, owns its own deployment pipeline, and talks to the others through typed boundaries.

  • API (apps/api). Owns security, databases, sessions, JWT cookies, background queues (BullMQ), email delivery, and the audit log trail.
  • UI (apps/ui). Owns the browser experience, local client states, i18n, queries, and routing via Vite and React 19.
  • Infra (infra-template). Owns Traefik TLS routing, VPS setups via OpenTofu, container provisioning, backups, and metrics overlays.
flowchart LR
  browser[Browser SPA]
  api[API Bun Elysia]
  data[(Postgres)]
  cache[(Valkey)]
  browser -->|HTTPS JSON OpenAPI| api
  api --> data
  api --> cache

Left to right: a browser SPA calls the Bun + Elysia API over HTTPS using a typed OpenAPI contract; the API alone talks to Postgres for durable state and to Valkey for cache and queue work. No browser-to-database path exists.

The API publishes OpenAPI at /swagger/json. The UI runs bun run generate:api to refresh schema.d.ts. openapi-fetch rejects invalid paths and bodies at compile time. See OpenAPI client and Repository layout for wiring.

In production, Traefik serves the public site on the apex (example.com) and the SPA and API on app.example.com (/ and /api/*). The app host is one origin, which keeps TLS and cookies simple. The site is a separate static host with no cookies and no API calls. The app workspaces stay isolated, and the Docker images stay separate.

  • Independent Deploys. Change the UI codebase without rebuilding or redeploying the API image. Tweak styling or text with absolute isolation.
  • Optimized Runtimes. Vite + React keep local UI feedback instant, while Elysia + Bun keep API endpoints and queue processing fast.
  • Hardened Boundaries. Auth, database access, and environment variables stay locked in the API container. No credentials ever bleed to the browser.
  • Focused Workspaces. Load only the repository you are actively working on. Teammates and agents stay bounded by their specific layer rules.