Skip to content

Architecture

harshcode1 edited this page Jun 20, 2026 · 1 revision

Architecture

BetterMind is a single Next.js 14 application using the App Router. The same deployment serves the UI (React Server/Client Components) and the backend (/api/* Route Handlers), talking to MongoDB and a few optional external services.

System diagram

┌─────────────────────────────────────────────────────────────────────┐
│                          Next.js 14 (App Router)                       │
│                                                                         │
│   ┌─────────────────────────┐         ┌──────────────────────────────┐ │
│   │     Client Components    │  fetch  │        Route Handlers         │ │
│   │                          │ ──────► │                               │ │
│   │  AuthContext             │  JSON   │  /api/auth/*    (login, 2FA)  │ │
│   │  (user + guest + gate)   │ ◄────── │  /api/mood, /api/assessment   │ │
│   │                          │         │  /api/chat       (OpenAI)     │ │
│   │  Pages:                  │         │  /api/doctors, /appointments  │ │
│   │  dashboard, mood,        │         │  /api/doctor/*  /api/admin/*  │ │
│   │  assessment, chat,       │         │                               │ │
│   │  doctors, appointments,  │         │  verifyAuth() on every        │ │
│   │  resources, settings     │         │  protected handler            │ │
│   └─────────────────────────┘         └───────────────┬───────────────┘ │
└──────────────────────────────────────────────────────┼─────────────────┘
                                                         │
        ┌────────────────────┬────────────────────┬─────┴──────────────┐
        │                    │                    │                     │
  ┌─────▼──────┐      ┌──────▼──────┐      ┌──────▼──────┐      ┌────────▼────────┐
  │  MongoDB   │      │   OpenAI    │      │ Google APIs │      │  otplib (TOTP)  │
  │  (driver)  │      │ gpt-4o-mini │      │  Calendar   │      │   + AES crypto  │
  └────────────┘      └─────────────┘      └─────────────┘      └─────────────────┘
   required            optional             optional             local

Request lifecycle (protected route)

  1. A client page calls fetch('/api/...'). The browser automatically attaches the httpOnly token cookie.
  2. The Route Handler reads the cookie and calls verifyAuth(token) from lib/authServer.js.
  3. verifyAuth checks an in-memory cache (5-minute TTL keyed by token). On a miss it jwt.verifys the token and confirms the user still exists in MongoDB, then caches the result.
  4. The handler enforces role (patient / doctor / admin) and returns JSON.
  5. The client renders. AuthContext already knows the current user from /api/auth/check on mount.

Rendering model

  • Client Components drive the interactive pages ('use client') because they rely on AuthContext, animations, and live data fetching.
  • Route Handlers are marked export const dynamic = 'force-dynamic' because they depend on per-request cookies and must never be statically cached.
  • Pages that read useSearchParams() (e.g. login, login/2fa, appointments/new) are wrapped in <Suspense> to satisfy the App Router's streaming requirements.

Data collections (MongoDB)

Collection Purpose Notable fields
users All accounts name, email, password (bcrypt), role, verified, twoFactorAuth
doctors Doctor profiles userId, specialty, credentials, licenseNumber, workingHours, reviews[], averageRating, googleTokens, rejected, rejectionReason
moods Daily mood logs userId, mood (1–10), activities[], notes, createdAt
assessments PHQ-9 / GAD-7 results userId, phq9Score, gad7Score, phq9Answers[], gad7Answers[], severities, date
appointments Bookings patientId, doctorId, dateTime, status, googleEventId, notes

Key design decisions

  • Custom JWT over a turnkey auth framework. Gives full control of the 2FA challenge (issue the JWT only after TOTP verification) and consistent role gating. next-auth was removed during the audit because it was installed but unused — mixing two auth systems is a liability.
  • Auth-result caching. verifyAuth caches verification per token for 5 minutes to avoid a DB round-trip on every single API call.
  • Graceful degradation by default. The AI chat falls back to keyword→specialist matching without OPENAI_API_KEY; Calendar sync no-ops without OAuth tokens; the MongoDB URI check is deferred to request time so the app can boot in environments where it's intentionally absent.
  • Guest Mode is a client concern only. No fake server session is created. Demo data is generated client-side and writes are intercepted, so the database is never touched by a guest. See Guest-Mode.
  • Reusable rate-limiter factory instead of bespoke logic per route — see Authentication-and-Security.

Related

Clone this wiki locally