# achille010/scrutiq architecture

> Architecture diagram of the GitHub repository achille010/scrutiq, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-09-29). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/achille010/scrutiq
- Repository: https://github.com/achille010/scrutiq

## Overview

Scrutiq is a recruiter-facing AI resume-screening and applicant-ranking platform. Recruiters define job criteria, upload candidate documents, review extracted profiles, run screening, and use scored shortlists to guide hiring decisions. The map also includes account access, analytics, chat, and outreach as documented product capabilities. README architecture and sampled controllers/services support the main API and ingestion links; screening, chat, and some frontend wiring are represented only where the tree or README identifies them, so uncertain internal calls are omitted.

Main entry points: [`client/src/app`](https://github.com/achille010/scrutiq/tree/main/client/src/app) (Recruiter dashboard), [`server/src/app.ts`](https://github.com/achille010/scrutiq/blob/main/server/src/app.ts) (Express API), [`server/src/controllers/stats.controller.ts`](https://github.com/achille010/scrutiq/blob/main/server/src/controllers/stats.controller.ts) (Recruiting analytics), [`server/src/services/applicants.service.ts`](https://github.com/achille010/scrutiq/blob/main/server/src/services/applicants.service.ts) (Profile ingestion)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_workspace["Recruiter workspace"]
  node_dashboard["Recruiter dashboard"]
  node_clientstate["Client state"]
  node_clientapi["API client<br/>[api.ts]"]
  node_stats["Recruiting analytics"]
  node_chat["Recruiter chat<br/>[chat.service.ts]"]
end

subgraph group_access["API and access"]
  node_api["Express API<br/>[app.ts]"]
  node_authroutes["Auth routes<br/>[auth.routes.ts]"]
  node_authcontroller["Auth controller<br/>[auth.controller.ts]"]
  node_authservice["Auth service<br/>[auth.service.ts]"]
  node_jobroutes["Job routes<br/>[jobs.routes.ts]"]
  node_jobcontroller["Job controller<br/>[jobs.controller.ts]"]
end

subgraph group_intake["Candidate intake"]
  node_applicantsroutes["Applicant routes"]
  node_applicantscontroller["Applicant controller"]
  node_applicantsservice["Profile ingestion"]
  node_parser["Document parsing<br/>[parser.ts]"]
end

subgraph group_evaluation["Screening and ranking"]
  node_jobservice["Job service<br/>[jobs.service.ts]"]
  node_screenroutes["Screening routes"]
  node_screencontroller["Screening controller"]
  node_screenservice["Candidate scoring"]
  node_shortlist["Ranked shortlist<br/>[page.tsx]"]
end

subgraph group_records["Records and integrations"]
  node_gemini["Gemini AI<br/>[gemini.service.ts]"]
  node_email["Email delivery<br/>[email.service.ts]"]
  node_applicantdb[("Applicant records<br/>[Applicant.model.ts]")]
  node_jobdb[("Job records<br/>[Job.model.ts]")]
  node_screeningdb[("Screening records<br/>[Screening.model.ts]")]
  node_userdb[("Recruiter accounts<br/>[User.model.ts]")]
end

node_recruiter(("Recruiter"))
node_mongodb[("MongoDB")]

node_recruiter -->|"uses"| node_dashboard
node_dashboard -->|"updates"| node_clientstate
node_clientstate -->|"requests"| node_clientapi
node_clientapi -->|"calls"| node_api
node_api -->|"dispatches"| node_authroutes
node_authroutes -->|"routes to"| node_authcontroller
node_authcontroller -->|"authenticates"| node_authservice
node_authservice -->|"reads/writes"| node_userdb
node_api -->|"dispatches"| node_jobroutes
node_jobroutes -->|"routes to"| node_jobcontroller
node_jobcontroller -->|"manages criteria"| node_jobservice
node_jobservice -->|"reads/writes"| node_jobdb
node_api -->|"dispatches"| node_applicantsroutes
node_applicantsroutes -->|"routes to"| node_applicantscontroller
node_applicantscontroller -->|"ingests profiles"| node_applicantsservice
node_applicantsservice -->|"extracts text"| node_parser
node_applicantsservice -->|"extracts profiles"| node_gemini
node_applicantsservice -->|"reads/writes"| node_applicantdb
node_api -->|"dispatches"| node_screenroutes
node_screenroutes -->|"routes to"| node_screencontroller
node_screencontroller -->|"screens candidates"| node_screenservice
node_screenservice -->|"scores matches"| node_gemini
node_screenservice -->|"reads/writes"| node_screeningdb
node_screenservice -->|"provides rankings"| node_shortlist
node_dashboard -->|"reviews"| node_shortlist
node_dashboard -->|"views metrics"| node_stats
node_stats -->|"aggregates jobs"| node_jobdb
node_stats -->|"counts candidates"| node_applicantdb
node_stats -->|"aggregates screenings"| node_screeningdb
node_dashboard -.->|"uses chat"| node_chat
node_applicantscontroller -->|"sends outreach"| node_email
node_authcontroller -->|"sends account mail"| node_email
node_mongodb -->|"persists"| node_userdb
node_mongodb -->|"persists"| node_jobdb
node_mongodb -->|"persists"| node_applicantdb
node_mongodb -->|"persists"| node_screeningdb

click node_dashboard "https://github.com/achille010/scrutiq/tree/main/client/src/app"
click node_clientstate "https://github.com/achille010/scrutiq/tree/main/client/src/store"
click node_clientapi "https://github.com/achille010/scrutiq/blob/main/client/src/lib/api.ts"
click node_api "https://github.com/achille010/scrutiq/blob/main/server/src/app.ts"
click node_authroutes "https://github.com/achille010/scrutiq/blob/main/server/src/routes/auth.routes.ts"
click node_authcontroller "https://github.com/achille010/scrutiq/blob/main/server/src/controllers/auth.controller.ts"
click node_authservice "https://github.com/achille010/scrutiq/blob/main/server/src/services/auth.service.ts"
click node_jobroutes "https://github.com/achille010/scrutiq/blob/main/server/src/routes/jobs.routes.ts"
click node_jobcontroller "https://github.com/achille010/scrutiq/blob/main/server/src/controllers/jobs.controller.ts"
click node_jobservice "https://github.com/achille010/scrutiq/blob/main/server/src/services/jobs.service.ts"
click node_applicantsroutes "https://github.com/achille010/scrutiq/blob/main/server/src/routes/applicants.routes.ts"
click node_applicantscontroller "https://github.com/achille010/scrutiq/blob/main/server/src/controllers/applicants.controller.ts"
click node_applicantsservice "https://github.com/achille010/scrutiq/blob/main/server/src/services/applicants.service.ts"
click node_parser "https://github.com/achille010/scrutiq/blob/main/server/src/utils/parser.ts"
click node_screenroutes "https://github.com/achille010/scrutiq/blob/main/server/src/routes/screening.routes.ts"
click node_screencontroller "https://github.com/achille010/scrutiq/blob/main/server/src/controllers/screening.controller.ts"
click node_screenservice "https://github.com/achille010/scrutiq/blob/main/server/src/services/screening.service.ts"
click node_gemini "https://github.com/achille010/scrutiq/blob/main/server/src/services/gemini.service.ts"
click node_shortlist "https://github.com/achille010/scrutiq/blob/main/client/src/app/dashboard/jobs/%5Bid%5D/shortlist/page.tsx"
click node_stats "https://github.com/achille010/scrutiq/blob/main/server/src/controllers/stats.controller.ts"
click node_chat "https://github.com/achille010/scrutiq/blob/main/server/src/services/chat.service.ts"
click node_email "https://github.com/achille010/scrutiq/blob/main/server/src/services/email.service.ts"
click node_applicantdb "https://github.com/achille010/scrutiq/blob/main/server/src/models/Applicant.model.ts"
click node_jobdb "https://github.com/achille010/scrutiq/blob/main/server/src/models/Job.model.ts"
click node_screeningdb "https://github.com/achille010/scrutiq/blob/main/server/src/models/Screening.model.ts"
click node_userdb "https://github.com/achille010/scrutiq/blob/main/server/src/models/User.model.ts"

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_dashboard,node_clientstate,node_clientapi,node_stats,node_chat toneBlue
class node_api,node_authroutes,node_authcontroller,node_authservice,node_jobroutes,node_jobcontroller,node_mongodb toneAmber
class node_applicantsroutes,node_applicantscontroller,node_applicantsservice,node_parser toneMint
class node_jobservice,node_screenroutes,node_screencontroller,node_screenservice,node_shortlist toneRose
class node_gemini,node_email,node_applicantdb,node_jobdb,node_screeningdb,node_userdb,node_recruiter toneIndigo
```

## Components

### Recruiter workspace

- [Recruiter dashboard](https://github.com/achille010/scrutiq/tree/main/client/src/app): `client/src/app`
- [Client state](https://github.com/achille010/scrutiq/tree/main/client/src/store): `client/src/store`
- [API client](https://github.com/achille010/scrutiq/blob/main/client/src/lib/api.ts): `client/src/lib/api.ts`
- [Recruiting analytics](https://github.com/achille010/scrutiq/blob/main/server/src/controllers/stats.controller.ts): `server/src/controllers/stats.controller.ts`
- [Recruiter chat](https://github.com/achille010/scrutiq/blob/main/server/src/services/chat.service.ts): `server/src/services/chat.service.ts`

### API and access

- [Express API](https://github.com/achille010/scrutiq/blob/main/server/src/app.ts): `server/src/app.ts`
- [Auth routes](https://github.com/achille010/scrutiq/blob/main/server/src/routes/auth.routes.ts): `server/src/routes/auth.routes.ts`
- [Auth controller](https://github.com/achille010/scrutiq/blob/main/server/src/controllers/auth.controller.ts): `server/src/controllers/auth.controller.ts`
- [Auth service](https://github.com/achille010/scrutiq/blob/main/server/src/services/auth.service.ts): `server/src/services/auth.service.ts`
- [Job routes](https://github.com/achille010/scrutiq/blob/main/server/src/routes/jobs.routes.ts): `server/src/routes/jobs.routes.ts`
- [Job controller](https://github.com/achille010/scrutiq/blob/main/server/src/controllers/jobs.controller.ts): `server/src/controllers/jobs.controller.ts`

### Candidate intake

- [Applicant routes](https://github.com/achille010/scrutiq/blob/main/server/src/routes/applicants.routes.ts): `server/src/routes/applicants.routes.ts`
- [Applicant controller](https://github.com/achille010/scrutiq/blob/main/server/src/controllers/applicants.controller.ts): `server/src/controllers/applicants.controller.ts`
- [Profile ingestion](https://github.com/achille010/scrutiq/blob/main/server/src/services/applicants.service.ts): `server/src/services/applicants.service.ts`
- [Document parsing](https://github.com/achille010/scrutiq/blob/main/server/src/utils/parser.ts): `server/src/utils/parser.ts`

### Screening and ranking

- [Job service](https://github.com/achille010/scrutiq/blob/main/server/src/services/jobs.service.ts): `server/src/services/jobs.service.ts`
- [Screening routes](https://github.com/achille010/scrutiq/blob/main/server/src/routes/screening.routes.ts): `server/src/routes/screening.routes.ts`
- [Screening controller](https://github.com/achille010/scrutiq/blob/main/server/src/controllers/screening.controller.ts): `server/src/controllers/screening.controller.ts`
- [Candidate scoring](https://github.com/achille010/scrutiq/blob/main/server/src/services/screening.service.ts): `server/src/services/screening.service.ts`
- [Ranked shortlist](https://github.com/achille010/scrutiq/blob/main/client/src/app/dashboard/jobs/%5Bid%5D/shortlist/page.tsx): `client/src/app/dashboard/jobs/[id]/shortlist/page.tsx`

### Records and integrations

- [Gemini AI](https://github.com/achille010/scrutiq/blob/main/server/src/services/gemini.service.ts): `server/src/services/gemini.service.ts`
- [Email delivery](https://github.com/achille010/scrutiq/blob/main/server/src/services/email.service.ts): `server/src/services/email.service.ts`
- [Applicant records](https://github.com/achille010/scrutiq/blob/main/server/src/models/Applicant.model.ts): `server/src/models/Applicant.model.ts`
- [Job records](https://github.com/achille010/scrutiq/blob/main/server/src/models/Job.model.ts): `server/src/models/Job.model.ts`
- [Screening records](https://github.com/achille010/scrutiq/blob/main/server/src/models/Screening.model.ts): `server/src/models/Screening.model.ts`
- [Recruiter accounts](https://github.com/achille010/scrutiq/blob/main/server/src/models/User.model.ts): `server/src/models/User.model.ts`

### Other components

- **Recruiter**
- **MongoDB**

## Connections

- Recruiter → Recruiter dashboard: uses
- Recruiter dashboard → Client state: updates
- Client state → API client: requests
- API client → Express API: calls
- Express API → Auth routes: dispatches
- Auth routes → Auth controller: routes to
- Auth controller → Auth service: authenticates
- Auth service → Recruiter accounts: reads/writes
- Express API → Job routes: dispatches
- Job routes → Job controller: routes to
- Job controller → Job service: manages criteria
- Job service → Job records: reads/writes
- Express API → Applicant routes: dispatches
- Applicant routes → Applicant controller: routes to
- Applicant controller → Profile ingestion: ingests profiles
- Profile ingestion → Document parsing: extracts text
- Profile ingestion → Gemini AI: extracts profiles
- Profile ingestion → Applicant records: reads/writes
- Express API → Screening routes: dispatches
- Screening routes → Screening controller: routes to
- Screening controller → Candidate scoring: screens candidates
- Candidate scoring → Gemini AI: scores matches
- Candidate scoring → Screening records: reads/writes
- Candidate scoring → Ranked shortlist: provides rankings
- Recruiter dashboard → Ranked shortlist: reviews
- Recruiter dashboard → Recruiting analytics: views metrics
- Recruiting analytics → Job records: aggregates jobs
- Recruiting analytics → Applicant records: counts candidates
- Recruiting analytics → Screening records: aggregates screenings
- Recruiter dashboard → Recruiter chat: uses chat
- Applicant controller → Email delivery: sends outreach
- Auth controller → Email delivery: sends account mail
- MongoDB → Recruiter accounts: persists
- MongoDB → Job records: persists
- MongoDB → Applicant records: persists
- MongoDB → Screening records: persists
