DocsArchitectureOverview

Overview

System architecture overview for Reqcore — a Nuxt 4 full-stack application with PostgreSQL, S3 storage, and multi-tenant data isolation.

Architecture Overview

Reqcore is a Nuxt 4 full-stack monolith with clear separation between client (app/) and server (server/) code. The system supports both managed deployment on Railway and self-hosted deployment via Docker Compose.

High-Level Architecture

┌─────────────────────────────────────────────────────┐
│                    Browser                           │
│  ┌──────────────────────────────────────────────┐   │
│  │  Nuxt App (Vue 3 + SSR)                      │   │
│  │  • Pages / Components / Composables          │   │
│  │  • Better Auth Vue Client                    │   │
│  │  • useFetch / $fetch → /api/*                │   │
│  └──────────────────┬───────────────────────────┘   │
└─────────────────────┼───────────────────────────────┘
                      │ HTTPS
┌─────────────────────┼───────────────────────────────┐
│  Cloudflare CDN     │                                │
│  • DNS, DDoS protection, edge caching               │
└─────────────────────┼───────────────────────────────┘
                      │ HTTPS
┌─────────────────────┼───────────────────────────────┐
│  Application Server                                  │
│  ┌──────────────────▼───────────────────────────┐   │
│  │  Nuxt / Nitro SSR Server                      │   │
│  └──────────┬───────────────────┬───────────────┘   │
│             │                   │                    │
│  ┌──────────▼──────┐   ┌───────▼────────────────┐   │
│  │  PostgreSQL 16  │   │  S3-Compatible Storage │   │
│  │  (Drizzle ORM)  │   │  (MinIO / Railway)     │   │
│  └─────────────────┘   └────────────────────────┘   │
└─────────────────────────────────────────────────────┘

Key Architectural Decisions

1. Multi-Tenancy via Organization Plugin

All domain tables (job, candidate, application, document) have an organizationId foreign key. Tenant isolation is enforced at the application layer:

Request → Auth Guard → Extract orgId from session → Scope all queries by orgId

The org ID never comes from user input (body, query, URL params). It is always derived from the authenticated session's activeOrganizationId.

2. Auto-Imported Server Utilities

Nitro auto-imports everything from server/utils/. Core utilities available without imports:

UtilityPurpose
dbDrizzle ORM client with schema
authBetter Auth instance
envZod-validated environment variables
generateJobSlugURL slug generation for public job pages
createRateLimiterIP-based sliding window rate limiter
uploadToS3 / deleteFromS3S3/MinIO file operations

3. Environment Validation

All environment variables are validated at startup via Zod in server/utils/env.ts. If any variable is missing or malformed, the server fails immediately. No runtime process.env access is allowed outside this file.

4. Auto-Applied Migrations

The server/plugins/migrations.ts plugin runs Drizzle migrations automatically on server startup. It uses a PostgreSQL advisory lock (pg_try_advisory_lock) to prevent race conditions in multi-instance deployments.

During server-side rendering, browser cookies are not automatically forwarded to internal API calls. All authenticated useFetch calls must include headers: useRequestHeaders(['cookie']) to forward the session cookie.

6. Server-Proxied Documents

Documents are always accessed through authenticated server endpoints that stream bytes from S3. Presigned URLs are never exposed to clients, preventing URL sharing or leakage of sensitive candidate data.

Data Model

organization (Better Auth)
├── job (draft → open → closed → archived)
│   └── application (new → screening → interview → offer → hired/rejected)
│       └── candidate
│           └── document (resume, cover_letter — stored in S3)
└── member (user ↔ organization with role)

All domain tables belong to exactly one organization. Candidates are deduplicated within each org by email.

Public vs Authenticated Routes

TypeServer PathPage PathAuth Required
Public APIserver/api/public/No
Public pagesapp/pages/jobs/, app/pages/blog/No
Authenticated APIserver/api/ (all other)Yes
Dashboard pagesapp/pages/dashboard/Yes

Next Steps