Request lifecycle
Three tiers
Presentation (React SPA)
The frontend is a single-page application built with React, Vite, and Tailwind CSS, served as static files from Firebase Hosting. All page components are lazy-loaded, server state is managed by TanStack React Query, and forms use React Hook Form with Zod. See Frontend architecture.Business logic (NestJS API)
The backend is a NestJS application exposed as a REST API under the global prefix/api/v1. It runs on Render’s Node 20 runtime on port 3001.
Key characteristics:
- Feature modules, each encapsulating one domain concern
ValidationPipewithwhitelist: truestrips unexpected fields from all requests- Global exception filters normalize all error responses
- Rate limiting via
@nestjs/throttler: 100 requests per minute - better-auth handler mounted on the Express instance at
/api/auth - Request timeout of 15 minutes for large report generation
Data (Neon PostgreSQL)
The database is a serverless PostgreSQL instance on Neon, managed entirely through Prisma Migrate. Prisma Client is the only database access layer; there is no raw SQL in application code.PrismaModule is global, and better-auth stores sessions and users in the same database. See the Data tab.
Deployment topology
The frontend and backend deploy independently. Firebase Hosting serves the SPA; Render runs the API; Neon holds the database; Cloudflare R2 stores uploaded files. The full topology and build commands are in Deployment. The frontend knows the backend URL throughVITE_API_BASE_URL, baked into the build at compile time.