The backend lives in apps/backend/ and runs a Hono API server on Node.js. It uses Prisma for schema management, Kysely for typed queries, PostgreSQL for storage, and Redis (Valkey) for caching.
apps/backend/src/
cache/ # Valkey (Redis) client and initialization
config/ # Environment config, app constants
db/ # Database client (Postgres + Kysely)
features/ # Domain-organized business logic
libs/ # Shared backend libraries and WebSocket setup
middleware/ # Error handling, validation, auth, file uploads
routes/ # HTTP route definitions (thin layer)
sockets/ # WebSocket event definitions
testing/ # Test utilities, mocks, setup
utils/ # Shared helpers
Features own business logic. Each domain (projects, notifications, auth) has its own folder in src/features/ with modules, database queries, mutations, and schemas. See How to organize features.
Routes are thin. Route files validate input, read context, call a module function, and return a response. No business logic in routes.
No try/catch. A centralized error middleware handles all errors. Throw typed errors (ApplicationError, AuthError, ValidationError) and let the middleware do its job.
Validation goes through Zod. Every route that accepts input uses the validate() middleware with a Zod schema. This powers both runtime validation and the end-to-end type bridge to the frontend SDK.
Reads go in db/queries/, writes go in db/mutations/. See Prisma and Kysely.