# khairul-anik-qp/qpbd-office architecture

> Architecture diagram of the GitHub repository khairul-anik-qp/qpbd-office, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-28). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/khairul-anik-qp/qpbd-office
- Repository: https://github.com/khairul-anik-qp/qpbd-office

## Overview

1. This is a pnpm workspace monorepo with three meaningful boundaries: `apps/web` for the PWA frontend, `apps/api` for the NestJS backend, and `packages/shared` for domain logic and shared constants/types used by both sides.

2. `packages/shared` is the domain contract layer. It contains request/status enums, user types, location/type constants, assignment helpers, operating-window logic, staff-count logic, and shared icon mappings. Both web and API import from here, so architecture diagrams should show it as the source of truth for cross-cutting business rules.

3. The backend is a NestJS 10 application in `apps/api`. It is organized by feature modules: auth, users, admin, staff, requests, assignment, SSE, push, reminders, email, and Prisma access. The backend owns all persistence, authorization, routing decisions, notifications, and background maintenance.

4. PostgreSQL is the primary system of record. Prisma sits between the API and the database, with migrations defining schema evolution for users, requests, push subscriptions, availability timestamps, favorites, cancellation/discard state, and related request lifecycle fields.

5. Authentication is Google OAuth plus JWT. The frontend sends Google sign-in credentials to `/api/auth/google`, receives a session token for active users, and routes based on role. New users are created as pending and must be approved or registered before accessing employee/staff areas.

6. The frontend is a React 19/Vite PWA in `apps/web`, split into role-specific shells: employee, staff, and admin. These shells are lazy-loaded UI boundaries that map directly to the three user roles and their workflows, rather than a single generic app screen.

7. Real-time updates use two channels: REST for commands and SSE for live state changes. The backend exposes `/sse/events`, and the web app has hooks and stores for SSE connection state, request synchronization, pending counts, and tab badges. Architecture diagrams should show SSE as a push-only event stream from API to clients, not a bidirectional socket.

8. Push notifications are a separate delivery path from SSE. The API stores push subscriptions and can send Web Push / FCM notifications, while the staff UI has setup and prompt components for enabling notifications. This matters because staff updates arrive both in-browser and out-of-browser.

9. The request lifecycle is the core business flow. Employees create requests through the web UI; the assignment service picks a staff target; staff accept, forward, and complete requests; the employee view reflects status changes live. The request states include `new`, `progress`, `done`, and `discarded`, with midnight auto-discard for stale open requests within the configured operating window.

10. Staff availability is its own subsystem because it affects routing and visibility. The API exposes staff roster and availability updates, and includes auto-reset/reminder services for busy status and stale “new” items. The frontend staff shell is organized around tabs for New, In progress, and Done.

11. There is an admin approval workflow for onboarding. Admin endpoints expose a pending queue and approval/rejection actions, while the admin UI shows the queue and staff/profile setup. Bootstrap admins are created from `BOOTSTRAP_ADMIN_EMAILS` on first login, which is an operational backdoor for initial setup.

12. Deployment is designed for single-origin production. The built web app is served alongside the API container, with Caddy and Docker Compose used for production orchestration. In development, Vite proxies `/api` and `/sse` to the API, so the browser still experiences one logical application surface.

13. Background jobs are part of the backend, not the frontend. The reminders service, request expiry service, and availability reset service run server-side to enforce time-based workflow rules independent of active clients.

14. The main diagram should therefore show four layers: browser/PWA shells, NestJS feature modules, Prisma/PostgreSQL, and external services such as Google OAuth, push providers, and optional email delivery. The key data flows are sign-in, request creation and status changes, live event broadcast, and notification delivery.

Main entry points: [`apps/api/src/prisma/prisma.module.ts`](https://github.com/khairul-anik-qp/qpbd-office/blob/main/apps/api/src/prisma/prisma.module.ts) (Prisma Access), [`apps/web/src/router.tsx`](https://github.com/khairul-anik-qp/qpbd-office/blob/main/apps/web/src/router.tsx) (Router), [`apps/api/src/requests/requests.module.ts`](https://github.com/khairul-anik-qp/qpbd-office/blob/main/apps/api/src/requests/requests.module.ts) (Requests Module), [`packages/shared/src/index.ts`](https://github.com/khairul-anik-qp/qpbd-office/blob/main/packages/shared/src/index.ts) (Domain Contract)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_browser["Browser / PWA"]
  node_web_router["Router<br/>[router.tsx]"]
  node_web_employee["Employee Shell<br/>PWA shell<br/>[EmployeeShell.tsx]"]
  node_web_staff["Staff Shell<br/>PWA shell<br/>[StaffShell.tsx]"]
  node_web_admin["Admin Shell<br/>PWA shell<br/>[AdminShell.tsx]"]
  node_web_realtime["Realtime Sync<br/>client sync<br/>[RealtimeSync.tsx]"]
  node_web_push["Push Setup<br/>client notifications"]
end

subgraph group_api["NestJS API"]
  node_api_auth["Auth Module<br/>NestJS auth<br/>[auth.module.ts]"]
  node_api_requests["Requests Module<br/>NestJS feature<br/>[requests.module.ts]"]
  node_api_staff["Staff Module<br/>NestJS feature<br/>[staff.module.ts]"]
  node_api_assignment["Assignment Service<br/>NestJS service"]
  node_api_admin["Admin Module<br/>NestJS feature<br/>[admin.module.ts]"]
  node_api_sse["SSE Module<br/>NestJS stream<br/>[sse.module.ts]"]
  node_api_push["Push Module<br/>NestJS notifications<br/>[push.module.ts]"]
  node_api_reminders["Reminders<br/>background jobs"]
  node_api_email["Email Service<br/>delivery service<br/>[email.module.ts]"]
  node_api_prisma["Prisma Access<br/>db adapter<br/>[prisma.module.ts]"]
end

subgraph group_shared["Shared Contract"]
  node_shared_contract["Domain Contract<br/>shared package<br/>[index.ts]"]
  node_shared_requests["Request Rules<br/>domain rules<br/>[requests.ts]"]
  node_shared_staff["Staff Rules<br/>domain rules<br/>[staff-count.ts]"]
  node_shared_assignment["Assignment Logic<br/>domain rules<br/>[assignment.ts]"]
  node_shared_window["Operating Window<br/>domain rules"]
end

subgraph group_data["Persistence"]
  node_db_schema[("Schema<br/>[schema.prisma]")]
  node_postgres[("PostgreSQL<br/>system of record")]
end

subgraph group_external["External Services"]
  node_google_oauth(("Google OAuth<br/>identity provider"))
  node_push_provider(("Push Provider<br/>web push / fcm"))
  node_email_provider(("Email Provider<br/>mail delivery"))
end

node_web_router -->|"role routes"| node_web_employee
node_web_router -->|"role routes"| node_web_staff
node_web_router -->|"role routes"| node_web_admin
node_web_router -->|"login"| node_api_auth
node_web_employee -->|"uses rules"| node_shared_contract
node_web_staff -->|"uses rules"| node_shared_contract
node_web_admin -->|"uses rules"| node_shared_contract
node_web_realtime -->|"SSE"| node_api_sse
node_web_push -->|"setup"| node_api_push
node_api_auth -->|"OAuth"| node_google_oauth
node_api_auth -->|"session users"| node_api_prisma
node_api_admin -->|"approve users"| node_api_prisma
node_api_requests -->|"assign"| node_api_assignment
node_api_requests -->|"persist"| node_api_prisma
node_api_staff -->|"availability"| node_api_prisma
node_api_staff -->|"reset jobs"| node_api_reminders
node_api_requests -->|"expiry jobs"| node_api_reminders
node_api_sse -->|"live state"| node_api_requests
node_api_sse -->|"live state"| node_api_staff
node_api_push -->|"deliver"| node_push_provider
node_api_push -->|"subscriptions"| node_api_prisma
node_api_email -->|"deliver"| node_email_provider
node_api_prisma -->|"schema"| node_db_schema
node_db_schema -->|"storage"| node_postgres
node_shared_requests -->|"consumed by"| node_api_requests
node_shared_staff -->|"consumed by"| node_api_staff
node_shared_assignment -->|"consumed by"| node_api_assignment
node_shared_window -->|"consumed by"| node_api_reminders
node_shared_contract -->|"types"| node_web_router
node_shared_contract -->|"types"| node_api_auth

click node_web_router "https://github.com/khairul-anik-qp/qpbd-office/blob/main/apps/web/src/router.tsx"
click node_web_employee "https://github.com/khairul-anik-qp/qpbd-office/blob/main/apps/web/src/shells/employee/EmployeeShell.tsx"
click node_web_staff "https://github.com/khairul-anik-qp/qpbd-office/blob/main/apps/web/src/shells/staff/StaffShell.tsx"
click node_web_admin "https://github.com/khairul-anik-qp/qpbd-office/blob/main/apps/web/src/shells/admin/AdminShell.tsx"
click node_web_realtime "https://github.com/khairul-anik-qp/qpbd-office/blob/main/apps/web/src/components/RealtimeSync.tsx"
click node_web_push "https://github.com/khairul-anik-qp/qpbd-office/blob/main/apps/web/src/context/PushSetupContext.tsx"
click node_shared_contract "https://github.com/khairul-anik-qp/qpbd-office/blob/main/packages/shared/src/index.ts"
click node_shared_requests "https://github.com/khairul-anik-qp/qpbd-office/blob/main/packages/shared/src/requests.ts"
click node_shared_staff "https://github.com/khairul-anik-qp/qpbd-office/blob/main/packages/shared/src/staff-count.ts"
click node_shared_assignment "https://github.com/khairul-anik-qp/qpbd-office/blob/main/packages/shared/src/assignment.ts"
click node_shared_window "https://github.com/khairul-anik-qp/qpbd-office/blob/main/packages/shared/src/operating-window.ts"
click node_api_auth "https://github.com/khairul-anik-qp/qpbd-office/blob/main/apps/api/src/auth/auth.module.ts"
click node_api_requests "https://github.com/khairul-anik-qp/qpbd-office/blob/main/apps/api/src/requests/requests.module.ts"
click node_api_staff "https://github.com/khairul-anik-qp/qpbd-office/blob/main/apps/api/src/staff/staff.module.ts"
click node_api_assignment "https://github.com/khairul-anik-qp/qpbd-office/blob/main/apps/api/src/assignment/assignment.service.ts"
click node_api_admin "https://github.com/khairul-anik-qp/qpbd-office/blob/main/apps/api/src/admin/admin.module.ts"
click node_api_sse "https://github.com/khairul-anik-qp/qpbd-office/blob/main/apps/api/src/sse/sse.module.ts"
click node_api_push "https://github.com/khairul-anik-qp/qpbd-office/blob/main/apps/api/src/push/push.module.ts"
click node_api_reminders "https://github.com/khairul-anik-qp/qpbd-office/blob/main/apps/api/src/reminders/reminders.module.ts"
click node_api_email "https://github.com/khairul-anik-qp/qpbd-office/blob/main/apps/api/src/email/email.module.ts"
click node_api_prisma "https://github.com/khairul-anik-qp/qpbd-office/blob/main/apps/api/src/prisma/prisma.module.ts"
click node_db_schema "https://github.com/khairul-anik-qp/qpbd-office/blob/main/apps/api/prisma/schema.prisma"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_web_router,node_web_employee,node_web_staff,node_web_admin,node_web_realtime,node_web_push toneBlue
class node_api_auth,node_api_requests,node_api_staff,node_api_assignment,node_api_admin,node_api_sse,node_api_push,node_api_reminders,node_api_email,node_api_prisma toneAmber
class node_shared_contract,node_shared_requests,node_shared_staff,node_shared_assignment,node_shared_window toneMint
class node_db_schema,node_postgres toneRose
class node_google_oauth,node_push_provider,node_email_provider toneIndigo
```

## Components

### Browser / PWA

React/Vite client surfaces and client-side state.

- [Router](https://github.com/khairul-anik-qp/qpbd-office/blob/main/apps/web/src/router.tsx): web shell router · Routes users into role-specific shells and auth screens. · `apps/web/src/router.tsx`
- [Employee Shell](https://github.com/khairul-anik-qp/qpbd-office/blob/main/apps/web/src/shells/employee/EmployeeShell.tsx): PWA shell · Employee-facing workflow for creating and tracking requests. · `apps/web/src/shells/employee/EmployeeShell.tsx`
- [Staff Shell](https://github.com/khairul-anik-qp/qpbd-office/blob/main/apps/web/src/shells/staff/StaffShell.tsx): PWA shell · Staff-facing queue, availability, and request handling UI. · `apps/web/src/shells/staff/StaffShell.tsx`
- [Admin Shell](https://github.com/khairul-anik-qp/qpbd-office/blob/main/apps/web/src/shells/admin/AdminShell.tsx): PWA shell · Admin approval and onboarding workflow. · `apps/web/src/shells/admin/AdminShell.tsx`
- [Realtime Sync](https://github.com/khairul-anik-qp/qpbd-office/blob/main/apps/web/src/components/RealtimeSync.tsx): client sync · SSE connection state, request sync, and tab badge updates. · `apps/web/src/components/RealtimeSync.tsx`
- [Push Setup](https://github.com/khairul-anik-qp/qpbd-office/blob/main/apps/web/src/context/PushSetupContext.tsx): client notifications · Staff notification setup and permission prompts. · `apps/web/src/context/PushSetupContext.tsx`

### NestJS API

Backend feature modules, routing, background jobs, and delivery services.

- [Auth Module](https://github.com/khairul-anik-qp/qpbd-office/blob/main/apps/api/src/auth/auth.module.ts): NestJS auth · Google sign-in, JWT sessions, guards, and role checks. · `apps/api/src/auth/auth.module.ts`
- [Requests Module](https://github.com/khairul-anik-qp/qpbd-office/blob/main/apps/api/src/requests/requests.module.ts): NestJS feature · Request creation, lifecycle transitions, and list/query APIs. · `apps/api/src/requests/requests.module.ts`
- [Staff Module](https://github.com/khairul-anik-qp/qpbd-office/blob/main/apps/api/src/staff/staff.module.ts): NestJS feature · Availability, roster, and auto-reset/reminder flows. · `apps/api/src/staff/staff.module.ts`
- [Assignment Service](https://github.com/khairul-anik-qp/qpbd-office/blob/main/apps/api/src/assignment/assignment.service.ts): NestJS service · Chooses staff targets for new requests. · `apps/api/src/assignment/assignment.service.ts`
- [Admin Module](https://github.com/khairul-anik-qp/qpbd-office/blob/main/apps/api/src/admin/admin.module.ts): NestJS feature · Pending-user queue and onboarding approval actions. · `apps/api/src/admin/admin.module.ts`
- [SSE Module](https://github.com/khairul-anik-qp/qpbd-office/blob/main/apps/api/src/sse/sse.module.ts): NestJS stream · Push-only event stream for live client updates. · `apps/api/src/sse/sse.module.ts`
- [Push Module](https://github.com/khairul-anik-qp/qpbd-office/blob/main/apps/api/src/push/push.module.ts): NestJS notifications · Stores subscriptions and sends Web Push/FCM notifications. · `apps/api/src/push/push.module.ts`
- [Reminders](https://github.com/khairul-anik-qp/qpbd-office/blob/main/apps/api/src/reminders/reminders.module.ts): background jobs · Server-side reminder and maintenance jobs. · `apps/api/src/reminders/reminders.module.ts`
- [Email Service](https://github.com/khairul-anik-qp/qpbd-office/blob/main/apps/api/src/email/email.module.ts): delivery service · Optional email delivery path for backend notifications. · `apps/api/src/email/email.module.ts`
- [Prisma Access](https://github.com/khairul-anik-qp/qpbd-office/blob/main/apps/api/src/prisma/prisma.module.ts): db adapter · Typed persistence boundary between NestJS and the database. · `apps/api/src/prisma/prisma.module.ts`

### Shared Contract

Domain rules and cross-cutting types used by both web and API.

- [Domain Contract](https://github.com/khairul-anik-qp/qpbd-office/blob/main/packages/shared/src/index.ts): shared package · Source of truth for request states, users, staff rules, assignments, and operating windows. · `packages/shared/src/index.ts`
- [Request Rules](https://github.com/khairul-anik-qp/qpbd-office/blob/main/packages/shared/src/requests.ts): domain rules · Request lifecycle constants and helpers. · `packages/shared/src/requests.ts`
- [Staff Rules](https://github.com/khairul-anik-qp/qpbd-office/blob/main/packages/shared/src/staff-count.ts): domain rules · Availability, staffing, and roster helpers. · `packages/shared/src/staff-count.ts`
- [Assignment Logic](https://github.com/khairul-anik-qp/qpbd-office/blob/main/packages/shared/src/assignment.ts): domain rules · Target selection and assignment helpers. · `packages/shared/src/assignment.ts`
- [Operating Window](https://github.com/khairul-anik-qp/qpbd-office/blob/main/packages/shared/src/operating-window.ts): domain rules · Time-window logic for stale-item expiry and auto-discard behavior. · `packages/shared/src/operating-window.ts`

### Persistence

Prisma schema and PostgreSQL system of record.

- [Schema](https://github.com/khairul-anik-qp/qpbd-office/blob/main/apps/api/prisma/schema.prisma): prisma schema · Database schema and migration history for users, requests, push subscriptions, availability, and lifecycle fields. · `apps/api/prisma/schema.prisma`
- **PostgreSQL**: system of record · Primary persistent store for users, requests, and staff state.

### External Services

Identity, push delivery, and optional email providers.

- **Google OAuth**: identity provider · External sign-in provider for authentication.
- **Push Provider**: web push / fcm · Out-of-browser notification delivery destination.
- **Email Provider**: mail delivery · Optional email transport for backend notifications.

## Connections

- Router → Employee Shell: role routes · Routes employees into the employee shell.
- Router → Staff Shell: role routes · Routes staff into the staff shell.
- Router → Admin Shell: role routes · Routes admins into the admin shell.
- Router → Auth Module: login · Submits Google credentials and receives session state.
- Employee Shell → Domain Contract: uses rules · Renders and validates request states and helpers.
- Staff Shell → Domain Contract: uses rules · Uses shared staff and request semantics.
- Admin Shell → Domain Contract: uses rules · Uses shared user and approval semantics.
- Realtime Sync → SSE Module: SSE · Consumes push-only live events from the backend.
- Push Setup → Push Module: setup · Registers notification permissions and subscriptions.
- Auth Module → Google OAuth: OAuth · Authenticates users through Google.
- Auth Module → Prisma Access: session users · Creates or updates authenticated user records.
- Admin Module → Prisma Access: approve users · Reads pending users and applies approval decisions.
- Requests Module → Assignment Service: assign · Delegates staff selection for new requests.
- Requests Module → Prisma Access: persist · Stores request lifecycle changes.
- Staff Module → Prisma Access: availability · Reads and updates staff availability state.
- Staff Module → Reminders: reset jobs · Supports busy-status resets and stale-item maintenance.
- Requests Module → Reminders: expiry jobs · Enforces midnight auto-discard for stale requests.
- SSE Module → Requests Module: live state · Broadcasts request changes to connected clients.
- SSE Module → Staff Module: live state · Broadcasts staff availability changes to connected clients.
- Push Module → Push Provider: deliver · Sends Web Push or FCM notifications.
- Push Module → Prisma Access: subscriptions · Stores push subscriptions.
- Email Service → Email Provider: deliver · Sends outbound email notifications when used.
- Prisma Access → Schema: schema · Uses Prisma schema and migrations as persistence contract.
- Schema → PostgreSQL: storage · Defines the PostgreSQL data model.
- Request Rules → Requests Module: consumed by · Backend request logic is based on shared lifecycle rules.
- Staff Rules → Staff Module: consumed by · Backend staffing logic uses shared availability helpers.
- Assignment Logic → Assignment Service: consumed by · Assignment service uses shared target-selection rules.
- Operating Window → Reminders: consumed by · Background jobs use operating-window logic.
- Domain Contract → Router: types · Frontend imports shared domain types and constants.
- Domain Contract → Auth Module: types · Backend imports shared domain types and constants.
