Surplus logo
Surplus Docsby Sharing Excess
The Stack

The Stack

Surplus is one Bun workspace. This section is a guided tour of what lives in it — the apps you can run, the packages they share, and the scheduled jobs that keep things current.

Monorepo layout

PathRole
apps/client/React 19 + TanStack Router + Vite — the staff, driver, and partner web app
apps/server/Hono + ORPC API; also serves the generated OpenAPI spec and Scalar UI at /openapi
apps/docs/This documentation site (Next.js + Fumadocs)
packages/contracts/ORPC procedure contracts shared by client and server
packages/services/Domain logic as dependency-injected service classes
packages/postgres/Drizzle schema (the database source of truth) and the Neon client
packages/types/Zod schemas and the TypeScript types inferred from them
packages/utils/Pure helpers, constants, and business rules — no I/O
packages/redis/Upstash Redis client and cache/lock helpers
packages/sharedDeps/Curated re-exports of third-party dependencies
crons/Scheduled workers — analytics cache warming and backups
scripts/One-off migration and backfill utilities
tests/Playwright end-to-end tests

How to think about it

Two layers, one direction of dependency:

  • Apps wire up the real world — they create database clients, the Redis connection, the S3 client, and inject those into services. Apps are deployable; packages are not.
  • Packages hold everything reusable: the API contract, domain logic, schema, types, and utilities. They never import from apps/*, and they never read environment variables. That keeps them portable and testable.

This separation is what lets the same domain logic run inside the API server today and inside a cron worker or a script tomorrow, with different concrete dependencies injected each time.

Tour the pieces

Apps

Shared code

  • Shared packages — contracts, services, postgres, types, utils, redis, and sharedDeps, plus how they depend on each other.

Background jobs

Naming and data conventions

A few rules hold across every part of the workspace:

  • camelCase everywhere — tables, columns, files, CSS variables, and identifiers.
  • UUID primary keys — never auto-incrementing integers.
  • Unix epoch timestamps — stored as integers, not Date objects.

The full set is on the Conventions page.