Architecture
Overview
Section titled “Overview”Inntrig is a monorepo with three deployable apps (web, api, docs-dev) and two shared packages (db, shared). All three apps ship to Railway independently.
Browser → apps/web (React Router v7, SSR) ↓ server-side fetch apps/api (Hono) ↓ packages/db (Drizzle + PostgreSQL)apps/web
Section titled “apps/web”React Router v7 in framework mode (SSR). All rendering is server-side by default; React hydration enhances the experience progressively. Forms must work without JavaScript — this is an accessibility tool.
Auth is handled server-side: form actions POST to the API, receive a session token, and set an HttpOnly cookie. The web app never stores credentials client-side.
The /auth/* route is a transparent proxy to the API’s Better Auth handler, allowing the browser to interact with auth endpoints on the same origin.
apps/api
Section titled “apps/api”Hono API. Handles:
/health— health check/auth/*— Better Auth handler (sign-up, sign-in, sign-out, session)/projects,/audits,/reports,/results— CRUD for domain entities/standards— read-only access to audit standards and criteria/admin/*— staff-only user, workspace, and standard management/docs— interactive OpenAPI documentation (Scalar UI)/mcp— MCP server for AI tool integration
Packages
Section titled “Packages”@inntrig/db
Section titled “@inntrig/db”Single source of truth for the database. Exports:
db— Drizzle client (postgres.js driver)schema— all table definitionsauth— Better Auth instance (shared between API and any future server-side code)
@inntrig/shared
Section titled “@inntrig/shared”Zod schemas and TypeScript types shared between web and api. Ensures request/response shapes are validated and typed end-to-end.
UI components come from @eekodigital/raster, an external design system package. The web app applies a sand-palette product theme over Raster’s tokens via apps/web/app/theme.css.
Authentication
Section titled “Authentication”Better Auth with email/password. The auth instance lives in @inntrig/db so it shares the same Drizzle client and schema as the rest of the application.
Session token is stored in an HttpOnly cookie (better-auth.session_token). The web app’s server-side loaders read this cookie and validate the session against the API before rendering protected routes.
Deployment
Section titled “Deployment”Both apps deploy to Railway via git push. Railway provides managed Postgres in production — the same DATABASE_URL environment variable works for both local Docker and Railway.