# danushrajaram/ai-medical-voice-agent architecture

> Architecture diagram of the GitHub repository danushrajaram/ai-medical-voice-agent, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-08-14). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/danushrajaram/ai-medical-voice-agent
- Repository: https://github.com/danushrajaram/ai-medical-voice-agent

## Overview

#### Purpose and Runtime
This is a Next.js 14 App Router application for voice-based, AI-assisted medical consultations. Authenticated users select a doctor specialization, create a consultation session from symptoms, and conduct a VAPI voice conversation backed by Gemini 2.0 Flash through OpenRouter. The main runtime starts through Next.js pages and route handlers under `app/`; deployment targets Vercel.

#### Application Entry and Route Topology
The public landing entry is `app/page.tsx`, wrapped by global shell and styling in `app/layout.tsx` and `app/globals.css`. Authentication routes are isolated in `app/(auth)/sign-in/[[...sign-in]]/page.tsx` and `app/(auth)/sign-up/[[...sign-up]]/page.tsx`. The authenticated product surface begins at `app/(routes)/dashboard/page.tsx`, with a dashboard layout at `app/(routes)/dashboard/layout.tsx`.

#### Identity Boundary
Clerk provides Google/phone authentication and establishes the user boundary before dashboard use. Auth provider integration is located in `app/(auth)/provider.tsx`; request-level route protection is likely centralized in `middleware.ts`. The application exposes a user API endpoint at `app/api/users/route.tsx`, which is the server boundary for persisting or retrieving application-specific user data separate from Clerk identity.

#### Dashboard, Doctor Selection, and Session Creation
The dashboard composes doctor discovery, suggested doctors, prior consultation history, and session initiation. Its central UI components are `app/(routes)/dashboard/_components/DoctorsAgentList.tsx`, `app/(routes)/dashboard/_components/AddNewSessionDialog.tsx`, and `app/(routes)/dashboard/_components/HistoryList.tsx`. User context is shared client-side through `context/UserDetailContext.tsx`. The resulting session is navigated to the dynamic consultation route `app/(routes)/dashboard/medical-agent/[sessionId]/page.tsx`.

#### AI Consultation Boundary
Server-side API routes separate UI interaction from external AI services. `app/api/session-chat/route.tsx` handles session chat/consultation requests, while `app/api/suggest-doctors/route.tsx` generates or retrieves doctor recommendations. Model client/configuration resides in `config/OpenAiModel.tsx`; despite its name, the README identifies Gemini 2.0 Flash accessed through OpenRouter as the reasoning backend. VAPI is the external real-time voice layer invoked by the consultation experience.

#### Persistence and Session History
Neon PostgreSQL is accessed through Drizzle ORM. Database connection and schema definitions are concentrated in `config/db.tsx` and `config/schema.tsx`; versioned schema evolution is represented by `drizzle/0000_cute_queen_noir.sql` and `drizzle/0001_optimal_firestar.sql`. This persistence layer stores patient/application context and supports session history displayed in the dashboard.

#### Primary Flow
A visitor enters `app/page.tsx`, signs in via Clerk, and reaches the dashboard. They select a doctor and submit symptoms through the session dialog; the client calls server APIs to create or enrich the consultation context, persists it through Drizzle/PostgreSQL, then routes to the session-specific medical-agent page. That page connects the selected persona and session context to VAPI voice interaction and the OpenRouter/Gemini reasoning path. Completed or existing sessions feed back into dashboard history.

Main entry points: [`app/(routes)/dashboard/page.tsx`](https://github.com/danushrajaram/ai-medical-voice-agent/blob/main/app/(routes)/dashboard/page.tsx) (Dashboard), [`config/db.tsx`](https://github.com/danushrajaram/ai-medical-voice-agent/blob/main/config/db.tsx) (Drizzle database layer), [`app/api/session-chat/route.tsx`](https://github.com/danushrajaram/ai-medical-voice-agent/blob/main/app/api/session-chat/route.tsx) (Session chat API), [`app/(routes)/dashboard/medical-agent/[sessionId]/page.tsx`](https://github.com/danushrajaram/ai-medical-voice-agent/blob/main/app/(routes)/dashboard/medical-agent/%5BsessionId%5D/page.tsx) (Voice consultation)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_ui["Next.js UI"]
  node_landing["Landing page<br/>Next.js page<br/>[page.tsx]"]
  node_app_shell["Global app shell<br/>layout and styles<br/>[layout.tsx]"]
  node_auth_pages["Sign-in / sign-up<br/>auth pages<br/>[page.tsx]"]
  node_auth_provider["Clerk provider<br/>auth integration<br/>[provider.tsx]"]
  node_route_guard["Route protection<br/>middleware<br/>[middleware.ts]"]
  node_dashboard["Dashboard<br/>authenticated page<br/>[page.tsx]"]
  node_dashboard_layout["Dashboard layout<br/>authenticated layout<br/>[layout.tsx]"]
  node_doctor_discovery["Doctor discovery<br/>dashboard component"]
  node_session_dialog["New session dialog<br/>dashboard component"]
  node_history["Consultation history<br/>dashboard component<br/>[HistoryList.tsx]"]
  node_consultation_page["Voice consultation<br/>dynamic session page<br/>[page.tsx]"]
  node_user_context["User detail context<br/>client context"]
end

subgraph group_server["Server APIs"]
  node_user_api{{"User API<br/>route handler<br/>[route.tsx]"}}
  node_doctor_api{{"Doctor suggestions API<br/>route handler<br/>[route.tsx]"}}
  node_session_api{{"Session chat API<br/>route handler<br/>[route.tsx]"}}
  node_model_client["OpenRouter model client<br/>AI client config<br/>[OpenAiModel.tsx]"]
end

subgraph group_data["Data Layer"]
  node_drizzle[("Drizzle database layer<br/>connection and schema<br/>[db.tsx]")]
  node_migrations["Schema migrations<br/>SQL migrations"]
end

subgraph group_external["External Services"]
  node_clerk(("Clerk<br/>identity provider"))
  node_vapi(("VAPI<br/>voice platform"))
  node_gemini(("Gemini 2.0 Flash<br/>reasoning model"))
  node_neon[("Neon PostgreSQL<br/>managed database")]
  node_vercel(("Vercel<br/>deployment platform"))
end

node_landing -->|"sign in"| node_auth_pages
node_app_shell -->|"wraps"| node_landing
node_auth_provider -->|"authenticates with"| node_clerk
node_route_guard -->|"protects"| node_dashboard
node_auth_pages -->|"authenticated access"| node_dashboard
node_dashboard_layout -->|"wraps"| node_dashboard
node_dashboard -->|"shows"| node_doctor_discovery
node_dashboard -->|"opens"| node_session_dialog
node_dashboard -->|"shows"| node_history
node_dashboard -->|"uses"| node_user_context
node_doctor_discovery -->|"requests suggestions"| node_doctor_api
node_session_dialog -->|"submits symptoms"| node_session_api
node_session_api -->|"creates session"| node_consultation_page
node_dashboard -->|"navigates by session ID"| node_consultation_page
node_consultation_page -->|"starts voice session"| node_vapi
node_session_api -->|"requests reasoning"| node_model_client
node_doctor_api -->|"generates recommendations"| node_model_client
node_model_client -->|"via OpenRouter"| node_gemini
node_user_api -->|"reads and writes"| node_drizzle
node_session_api -->|"persists session context"| node_drizzle
node_history -->|"loads sessions"| node_drizzle
node_drizzle -->|"connects to"| node_neon
node_migrations -.->|"evolves schema"| node_drizzle
node_vercel -.->|"deploys application"| node_app_shell

click node_landing "https://github.com/danushrajaram/ai-medical-voice-agent/blob/main/app/page.tsx"
click node_app_shell "https://github.com/danushrajaram/ai-medical-voice-agent/blob/main/app/layout.tsx"
click node_auth_pages "https://github.com/danushrajaram/ai-medical-voice-agent/blob/main/app/(auth)/sign-in/%5B%5B...sign-in%5D%5D/page.tsx"
click node_auth_provider "https://github.com/danushrajaram/ai-medical-voice-agent/blob/main/app/(auth)/provider.tsx"
click node_route_guard "https://github.com/danushrajaram/ai-medical-voice-agent/blob/main/middleware.ts"
click node_dashboard "https://github.com/danushrajaram/ai-medical-voice-agent/blob/main/app/(routes)/dashboard/page.tsx"
click node_dashboard_layout "https://github.com/danushrajaram/ai-medical-voice-agent/blob/main/app/(routes)/dashboard/layout.tsx"
click node_doctor_discovery "https://github.com/danushrajaram/ai-medical-voice-agent/blob/main/app/(routes)/dashboard/_components/DoctorsAgentList.tsx"
click node_session_dialog "https://github.com/danushrajaram/ai-medical-voice-agent/blob/main/app/(routes)/dashboard/_components/AddNewSessionDialog.tsx"
click node_history "https://github.com/danushrajaram/ai-medical-voice-agent/blob/main/app/(routes)/dashboard/_components/HistoryList.tsx"
click node_consultation_page "https://github.com/danushrajaram/ai-medical-voice-agent/blob/main/app/(routes)/dashboard/medical-agent/%5BsessionId%5D/page.tsx"
click node_user_context "https://github.com/danushrajaram/ai-medical-voice-agent/blob/main/context/UserDetailContext.tsx"
click node_user_api "https://github.com/danushrajaram/ai-medical-voice-agent/blob/main/app/api/users/route.tsx"
click node_doctor_api "https://github.com/danushrajaram/ai-medical-voice-agent/blob/main/app/api/suggest-doctors/route.tsx"
click node_session_api "https://github.com/danushrajaram/ai-medical-voice-agent/blob/main/app/api/session-chat/route.tsx"
click node_model_client "https://github.com/danushrajaram/ai-medical-voice-agent/blob/main/config/OpenAiModel.tsx"
click node_drizzle "https://github.com/danushrajaram/ai-medical-voice-agent/blob/main/config/db.tsx"
click node_migrations "https://github.com/danushrajaram/ai-medical-voice-agent/blob/main/drizzle/0000_cute_queen_noir.sql"

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_landing,node_app_shell,node_auth_pages,node_auth_provider,node_route_guard,node_dashboard,node_dashboard_layout,node_doctor_discovery,node_session_dialog,node_history,node_consultation_page,node_user_context toneBlue
class node_user_api,node_doctor_api,node_session_api,node_model_client toneAmber
class node_drizzle,node_migrations toneMint
class node_clerk,node_vapi,node_gemini,node_neon,node_vercel toneRose
```

## Components

### Next.js UI

App Router pages and client components.

- [Landing page](https://github.com/danushrajaram/ai-medical-voice-agent/blob/main/app/page.tsx): Next.js page · `app/page.tsx`
- [Global app shell](https://github.com/danushrajaram/ai-medical-voice-agent/blob/main/app/layout.tsx): layout and styles · `app/layout.tsx`
- [Sign-in / sign-up](https://github.com/danushrajaram/ai-medical-voice-agent/blob/main/app/(auth)/sign-in/%5B%5B...sign-in%5D%5D/page.tsx): auth pages · `app/(auth)/sign-in/[[...sign-in]]/page.tsx`
- [Clerk provider](https://github.com/danushrajaram/ai-medical-voice-agent/blob/main/app/(auth)/provider.tsx): auth integration · `app/(auth)/provider.tsx`
- [Route protection](https://github.com/danushrajaram/ai-medical-voice-agent/blob/main/middleware.ts): middleware · `middleware.ts`
- [Dashboard](https://github.com/danushrajaram/ai-medical-voice-agent/blob/main/app/(routes)/dashboard/page.tsx): authenticated page · Composes discovery, history, and session initiation. · `app/(routes)/dashboard/page.tsx`
- [Dashboard layout](https://github.com/danushrajaram/ai-medical-voice-agent/blob/main/app/(routes)/dashboard/layout.tsx): authenticated layout · `app/(routes)/dashboard/layout.tsx`
- [Doctor discovery](https://github.com/danushrajaram/ai-medical-voice-agent/blob/main/app/(routes)/dashboard/_components/DoctorsAgentList.tsx): dashboard component · `app/(routes)/dashboard/_components/DoctorsAgentList.tsx`
- [New session dialog](https://github.com/danushrajaram/ai-medical-voice-agent/blob/main/app/(routes)/dashboard/_components/AddNewSessionDialog.tsx): dashboard component · Collects doctor selection and symptoms. · `app/(routes)/dashboard/_components/AddNewSessionDialog.tsx`
- [Consultation history](https://github.com/danushrajaram/ai-medical-voice-agent/blob/main/app/(routes)/dashboard/_components/HistoryList.tsx): dashboard component · `app/(routes)/dashboard/_components/HistoryList.tsx`
- [Voice consultation](https://github.com/danushrajaram/ai-medical-voice-agent/blob/main/app/(routes)/dashboard/medical-agent/%5BsessionId%5D/page.tsx): dynamic session page · `app/(routes)/dashboard/medical-agent/[sessionId]/page.tsx`
- [User detail context](https://github.com/danushrajaram/ai-medical-voice-agent/blob/main/context/UserDetailContext.tsx): client context · `context/UserDetailContext.tsx`

### Server APIs

Route handlers and AI integration.

- [User API](https://github.com/danushrajaram/ai-medical-voice-agent/blob/main/app/api/users/route.tsx): route handler · Persists or retrieves application-specific user data. · `app/api/users/route.tsx`
- [Doctor suggestions API](https://github.com/danushrajaram/ai-medical-voice-agent/blob/main/app/api/suggest-doctors/route.tsx): route handler · `app/api/suggest-doctors/route.tsx`
- [Session chat API](https://github.com/danushrajaram/ai-medical-voice-agent/blob/main/app/api/session-chat/route.tsx): route handler · Builds consultation context for AI interactions. · `app/api/session-chat/route.tsx`
- [OpenRouter model client](https://github.com/danushrajaram/ai-medical-voice-agent/blob/main/config/OpenAiModel.tsx): AI client config · Uses Gemini 2.0 Flash as the reasoning backend. · `config/OpenAiModel.tsx`

### Data Layer

Application persistence and migrations.

- [Drizzle database layer](https://github.com/danushrajaram/ai-medical-voice-agent/blob/main/config/db.tsx): connection and schema · Accesses Neon PostgreSQL and defines persisted records. · `config/db.tsx`
- [Schema migrations](https://github.com/danushrajaram/ai-medical-voice-agent/blob/main/drizzle/0000_cute_queen_noir.sql): SQL migrations · `drizzle/0000_cute_queen_noir.sql`

### External Services

Identity, voice, model, and hosting providers.

- **Clerk**: identity provider · Google and phone authentication.
- **VAPI**: voice platform · Real-time voice conversation layer.
- **Gemini 2.0 Flash**: reasoning model · Accessed through OpenRouter.
- **Neon PostgreSQL**: managed database
- **Vercel**: deployment platform

## Connections

- Landing page → Sign-in / sign-up: sign in
- Global app shell → Landing page: wraps
- Clerk provider → Clerk: authenticates with
- Route protection → Dashboard: protects
- Sign-in / sign-up → Dashboard: authenticated access
- Dashboard layout → Dashboard: wraps
- Dashboard → Doctor discovery: shows
- Dashboard → New session dialog: opens
- Dashboard → Consultation history: shows
- Dashboard → User detail context: uses
- Doctor discovery → Doctor suggestions API: requests suggestions
- New session dialog → Session chat API: submits symptoms
- Session chat API → Voice consultation: creates session
- Dashboard → Voice consultation: navigates by session ID
- Voice consultation → VAPI: starts voice session
- Session chat API → OpenRouter model client: requests reasoning
- Doctor suggestions API → OpenRouter model client: generates recommendations
- OpenRouter model client → Gemini 2.0 Flash: via OpenRouter
- User API → Drizzle database layer: reads and writes
- Session chat API → Drizzle database layer: persists session context
- Consultation history → Drizzle database layer: loads sessions
- Drizzle database layer → Neon PostgreSQL: connects to
- Schema migrations → Drizzle database layer: evolves schema
- Vercel → Global app shell: deploys application
