# kashif107/resumeguard architecture

> Architecture diagram of the GitHub repository kashif107/resumeguard, 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/kashif107/resumeguard
- Repository: https://github.com/kashif107/resumeguard

## Overview

This is an AI resume analyzer with a React client and an Express API backed by PostgreSQL, Redis/BullMQ, Cloudinary, and OpenRouter. The main workflow is authenticated PDF upload, text extraction and persistence, asynchronous scoring, then polling and rendering feedback. Authentication and resume-management routes are distinct supporting stages. The worker combines cached keyword matching with LLM scoring and handles failures through retries and a dead-letter queue. Some frontend wiring is documented in the README but its source was not excerpted; those links cite the README.

Main entry points: [`backend/workers/scoring.worker.js`](https://github.com/kashif107/resumeguard/blob/main/backend/workers/scoring.worker.js) (Scoring Worker), [`backend/controllers/resume.controller.js`](https://github.com/kashif107/resumeguard/blob/main/backend/controllers/resume.controller.js) (Resume Controller), [`frontend/app/lib/api.js`](https://github.com/kashif107/resumeguard/blob/main/frontend/app/lib/api.js) (API Client), [`frontend/app/routes/resume.jsx`](https://github.com/kashif107/resumeguard/blob/main/frontend/app/routes/resume.jsx) (Resume Results UI)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_client["Client"]
  node_auth_ui["Authentication UI<br/>[auth.jsx]"]
  node_home_ui["Resume List UI<br/>[home.jsx]"]
  node_upload_ui["Upload UI<br/>[upload.jsx]"]
  node_resume_ui["Resume Results UI<br/>[resume.jsx]"]
  node_wipe_ui["Wipe UI<br/>[wipe.jsx]"]
  node_api_client["API Client<br/>[api.js]"]
  node_file_uploader["File Uploader<br/>[FileUploader.jsx]"]
  node_utils["Client Utilities<br/>[utils.js]"]
  node_summary["Score Summary<br/>[Summary.jsx]"]
  node_ats["ATS Feedback<br/>[ATS.jsx]"]
  node_details["Score Details<br/>[Details.jsx]"]
  node_accordion["Feedback Accordion<br/>[Accordion.jsx]"]
  node_score_circle["Score Circle<br/>[ScoreCircle.jsx]"]
  node_score_gauge["Score Gauge<br/>[ScoreGauge.jsx]"]
  node_resume_card["Resume Card<br/>[ResumeCard.jsx]"]
end

subgraph group_api["API and Identity"]
  node_api_server["Express API<br/>[server.js]"]
  node_auth_routes["Auth Routes<br/>[auth.routes.js]"]
  node_auth_controller["Auth Controller<br/>[auth.controller.js]"]
  node_auth_middleware["JWT Middleware<br/>[auth.middleware.js]"]
  node_user_model["User Model<br/>[user.model.js]"]
end

subgraph group_resume["Resume Intake and Storage"]
  node_resume_routes["Resume Routes<br/>[resume.routes.js]"]
  node_upload_middleware["Upload Middleware"]
  node_resume_controller["Resume Controller"]
  node_pdf_service["PDF Service<br/>[pdf.service.js]"]
  node_cloudinary_service["Cloudinary Service"]
  node_resume_model["Resume Model<br/>[resume.model.js]"]
  node_postgres[("PostgreSQL<br/>[postgres.js]")]
end

subgraph group_scoring["Scoring Pipeline"]
  node_worker["Scoring Worker<br/>[scoring.worker.js]"]
  node_scoring_queue["Scoring Queue<br/>[scoring.queue.js]"]
  node_redis_connection["Redis Connection<br/>[connection.js]"]
  node_scoring_service["Scoring Service<br/>[scoring.service.js]"]
  node_cache_service["Feedback Cache<br/>[cache.service.js]"]
end

node_user(("Candidate"))
node_cloudinary["Cloudinary"]

node_user -->|"uses"| node_auth_ui
node_user -->|"submits PDF"| node_upload_ui
node_user -->|"views resumes"| node_home_ui
node_api_client -->|"calls API"| node_api_server
node_upload_ui -->|"uploads and polls"| node_api_client
node_home_ui -->|"lists resumes"| node_api_client
node_resume_ui -->|"polls result"| node_api_client
node_wipe_ui -->|"requests wipe"| node_api_client
node_file_uploader -->|"uses"| node_utils
node_resume_ui -->|"renders"| node_summary
node_resume_ui -->|"renders"| node_ats
node_resume_ui -->|"renders"| node_details
node_details -->|"renders"| node_accordion
node_summary -.->|"renders"| node_score_circle
node_summary -.->|"renders"| node_score_gauge
node_home_ui -.->|"renders"| node_resume_card
node_api_server -->|"mounts"| node_auth_routes
node_api_server -->|"mounts"| node_resume_routes
node_auth_routes -->|"dispatches"| node_auth_controller
node_auth_routes -->|"protects me"| node_auth_middleware
node_auth_controller -->|"reads and creates"| node_user_model
node_resume_routes -->|"protects routes"| node_auth_middleware
node_resume_routes -->|"parses upload"| node_upload_middleware
node_resume_routes -->|"dispatches"| node_resume_controller
node_resume_controller -->|"uploads PDF"| node_cloudinary_service
node_cloudinary_service -.->|"stores asset"| node_cloudinary
node_resume_controller -->|"extracts text"| node_pdf_service
node_resume_controller -->|"persists and reads"| node_resume_model
node_resume_controller -->|"enqueues job"| node_scoring_queue
node_resume_model -->|"queries"| node_postgres
node_scoring_queue -->|"uses connection"| node_redis_connection
node_worker -->|"connects"| node_redis_connection
node_worker -->|"loads and updates"| node_resume_model
node_worker -->|"loads resume"| node_postgres
node_worker -->|"scores resume"| node_scoring_service
node_scoring_service -->|"checks and writes"| node_cache_service
node_worker -->|"builds preview URL"| node_pdf_service

click node_auth_ui "https://github.com/kashif107/resumeguard/blob/main/frontend/app/routes/auth.jsx"
click node_home_ui "https://github.com/kashif107/resumeguard/blob/main/frontend/app/routes/home.jsx"
click node_upload_ui "https://github.com/kashif107/resumeguard/blob/main/frontend/app/routes/upload.jsx"
click node_resume_ui "https://github.com/kashif107/resumeguard/blob/main/frontend/app/routes/resume.jsx"
click node_wipe_ui "https://github.com/kashif107/resumeguard/blob/main/frontend/app/routes/wipe.jsx"
click node_api_client "https://github.com/kashif107/resumeguard/blob/main/frontend/app/lib/api.js"
click node_file_uploader "https://github.com/kashif107/resumeguard/blob/main/frontend/app/components/FileUploader.jsx"
click node_utils "https://github.com/kashif107/resumeguard/blob/main/frontend/app/lib/utils.js"
click node_summary "https://github.com/kashif107/resumeguard/blob/main/frontend/app/components/Summary.jsx"
click node_ats "https://github.com/kashif107/resumeguard/blob/main/frontend/app/components/ATS.jsx"
click node_details "https://github.com/kashif107/resumeguard/blob/main/frontend/app/components/Details.jsx"
click node_accordion "https://github.com/kashif107/resumeguard/blob/main/frontend/app/components/Accordion.jsx"
click node_score_circle "https://github.com/kashif107/resumeguard/blob/main/frontend/app/components/ScoreCircle.jsx"
click node_score_gauge "https://github.com/kashif107/resumeguard/blob/main/frontend/app/components/ScoreGauge.jsx"
click node_resume_card "https://github.com/kashif107/resumeguard/blob/main/frontend/app/components/ResumeCard.jsx"
click node_api_server "https://github.com/kashif107/resumeguard/blob/main/backend/server.js"
click node_auth_routes "https://github.com/kashif107/resumeguard/blob/main/backend/routes/auth.routes.js"
click node_auth_controller "https://github.com/kashif107/resumeguard/blob/main/backend/controllers/auth.controller.js"
click node_auth_middleware "https://github.com/kashif107/resumeguard/blob/main/backend/middleware/auth.middleware.js"
click node_user_model "https://github.com/kashif107/resumeguard/blob/main/backend/db/models/user.model.js"
click node_resume_routes "https://github.com/kashif107/resumeguard/blob/main/backend/routes/resume.routes.js"
click node_upload_middleware "https://github.com/kashif107/resumeguard/blob/main/backend/middleware/upload.middleware.js"
click node_resume_controller "https://github.com/kashif107/resumeguard/blob/main/backend/controllers/resume.controller.js"
click node_pdf_service "https://github.com/kashif107/resumeguard/blob/main/backend/services/pdf.service.js"
click node_cloudinary_service "https://github.com/kashif107/resumeguard/blob/main/backend/services/cloudinary.service.js"
click node_resume_model "https://github.com/kashif107/resumeguard/blob/main/backend/db/models/resume.model.js"
click node_postgres "https://github.com/kashif107/resumeguard/blob/main/backend/db/postgres.js"
click node_worker "https://github.com/kashif107/resumeguard/blob/main/backend/workers/scoring.worker.js"
click node_scoring_queue "https://github.com/kashif107/resumeguard/blob/main/backend/queues/scoring.queue.js"
click node_redis_connection "https://github.com/kashif107/resumeguard/blob/main/backend/queues/connection.js"
click node_scoring_service "https://github.com/kashif107/resumeguard/blob/main/backend/services/scoring.service.js"
click node_cache_service "https://github.com/kashif107/resumeguard/blob/main/backend/services/cache.service.js"

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_auth_ui,node_home_ui,node_upload_ui,node_resume_ui,node_wipe_ui,node_api_client,node_file_uploader,node_utils,node_summary,node_ats,node_details,node_accordion,node_score_circle,node_score_gauge,node_resume_card toneBlue
class node_api_server,node_auth_routes,node_auth_controller,node_auth_middleware,node_user_model toneAmber
class node_resume_routes,node_upload_middleware,node_resume_controller,node_pdf_service,node_cloudinary_service,node_resume_model,node_postgres toneMint
class node_worker,node_scoring_queue,node_redis_connection,node_scoring_service,node_cache_service toneRose
class node_user,node_cloudinary toneIndigo
```

## Components

### Client

- [Authentication UI](https://github.com/kashif107/resumeguard/blob/main/frontend/app/routes/auth.jsx): `frontend/app/routes/auth.jsx`
- [Resume List UI](https://github.com/kashif107/resumeguard/blob/main/frontend/app/routes/home.jsx): `frontend/app/routes/home.jsx`
- [Upload UI](https://github.com/kashif107/resumeguard/blob/main/frontend/app/routes/upload.jsx): `frontend/app/routes/upload.jsx`
- [Resume Results UI](https://github.com/kashif107/resumeguard/blob/main/frontend/app/routes/resume.jsx): `frontend/app/routes/resume.jsx`
- [Wipe UI](https://github.com/kashif107/resumeguard/blob/main/frontend/app/routes/wipe.jsx): `frontend/app/routes/wipe.jsx`
- [API Client](https://github.com/kashif107/resumeguard/blob/main/frontend/app/lib/api.js): `frontend/app/lib/api.js`
- [File Uploader](https://github.com/kashif107/resumeguard/blob/main/frontend/app/components/FileUploader.jsx): `frontend/app/components/FileUploader.jsx`
- [Client Utilities](https://github.com/kashif107/resumeguard/blob/main/frontend/app/lib/utils.js): `frontend/app/lib/utils.js`
- [Score Summary](https://github.com/kashif107/resumeguard/blob/main/frontend/app/components/Summary.jsx): `frontend/app/components/Summary.jsx`
- [ATS Feedback](https://github.com/kashif107/resumeguard/blob/main/frontend/app/components/ATS.jsx): `frontend/app/components/ATS.jsx`
- [Score Details](https://github.com/kashif107/resumeguard/blob/main/frontend/app/components/Details.jsx): `frontend/app/components/Details.jsx`
- [Feedback Accordion](https://github.com/kashif107/resumeguard/blob/main/frontend/app/components/Accordion.jsx): `frontend/app/components/Accordion.jsx`
- [Score Circle](https://github.com/kashif107/resumeguard/blob/main/frontend/app/components/ScoreCircle.jsx): `frontend/app/components/ScoreCircle.jsx`
- [Score Gauge](https://github.com/kashif107/resumeguard/blob/main/frontend/app/components/ScoreGauge.jsx): `frontend/app/components/ScoreGauge.jsx`
- [Resume Card](https://github.com/kashif107/resumeguard/blob/main/frontend/app/components/ResumeCard.jsx): `frontend/app/components/ResumeCard.jsx`

### API and Identity

- [Express API](https://github.com/kashif107/resumeguard/blob/main/backend/server.js): `backend/server.js`
- [Auth Routes](https://github.com/kashif107/resumeguard/blob/main/backend/routes/auth.routes.js): `backend/routes/auth.routes.js`
- [Auth Controller](https://github.com/kashif107/resumeguard/blob/main/backend/controllers/auth.controller.js): `backend/controllers/auth.controller.js`
- [JWT Middleware](https://github.com/kashif107/resumeguard/blob/main/backend/middleware/auth.middleware.js): `backend/middleware/auth.middleware.js`
- [User Model](https://github.com/kashif107/resumeguard/blob/main/backend/db/models/user.model.js): `backend/db/models/user.model.js`

### Resume Intake and Storage

- [Resume Routes](https://github.com/kashif107/resumeguard/blob/main/backend/routes/resume.routes.js): `backend/routes/resume.routes.js`
- [Upload Middleware](https://github.com/kashif107/resumeguard/blob/main/backend/middleware/upload.middleware.js): `backend/middleware/upload.middleware.js`
- [Resume Controller](https://github.com/kashif107/resumeguard/blob/main/backend/controllers/resume.controller.js): `backend/controllers/resume.controller.js`
- [PDF Service](https://github.com/kashif107/resumeguard/blob/main/backend/services/pdf.service.js): `backend/services/pdf.service.js`
- [Cloudinary Service](https://github.com/kashif107/resumeguard/blob/main/backend/services/cloudinary.service.js): `backend/services/cloudinary.service.js`
- [Resume Model](https://github.com/kashif107/resumeguard/blob/main/backend/db/models/resume.model.js): `backend/db/models/resume.model.js`
- [PostgreSQL](https://github.com/kashif107/resumeguard/blob/main/backend/db/postgres.js): `backend/db/postgres.js`

### Scoring Pipeline

- [Scoring Worker](https://github.com/kashif107/resumeguard/blob/main/backend/workers/scoring.worker.js): `backend/workers/scoring.worker.js`
- [Scoring Queue](https://github.com/kashif107/resumeguard/blob/main/backend/queues/scoring.queue.js): `backend/queues/scoring.queue.js`
- [Redis Connection](https://github.com/kashif107/resumeguard/blob/main/backend/queues/connection.js): `backend/queues/connection.js`
- [Scoring Service](https://github.com/kashif107/resumeguard/blob/main/backend/services/scoring.service.js): `backend/services/scoring.service.js`
- [Feedback Cache](https://github.com/kashif107/resumeguard/blob/main/backend/services/cache.service.js): `backend/services/cache.service.js`

### Other components

- **Candidate**
- **Cloudinary**

## Connections

- Candidate → Authentication UI: uses (evidence: `README.md`)
- Candidate → Upload UI: submits PDF (evidence: `README.md`)
- Candidate → Resume List UI: views resumes (evidence: `README.md`)
- API Client → Express API: calls API (evidence: `README.md`)
- Upload UI → API Client: uploads and polls (evidence: `README.md`)
- Resume List UI → API Client: lists resumes (evidence: `README.md`)
- Resume Results UI → API Client: polls result (evidence: `README.md`)
- Wipe UI → API Client: requests wipe (evidence: `README.md`)
- File Uploader → Client Utilities: uses (evidence: `frontend/app/components/FileUploader.jsx`)
- Resume Results UI → Score Summary: renders (evidence: `README.md`)
- Resume Results UI → ATS Feedback: renders (evidence: `README.md`)
- Resume Results UI → Score Details: renders (evidence: `README.md`)
- Score Details → Feedback Accordion: renders (evidence: `frontend/app/components/Details.jsx`)
- Score Summary → Score Circle: renders
- Score Summary → Score Gauge: renders
- Resume List UI → Resume Card: renders
- Express API → Auth Routes: mounts (evidence: `backend/server.js`)
- Express API → Resume Routes: mounts (evidence: `backend/server.js`)
- Auth Routes → Auth Controller: dispatches (evidence: `backend/routes/auth.routes.js`)
- Auth Routes → JWT Middleware: protects me (evidence: `backend/routes/auth.routes.js`)
- Auth Controller → User Model: reads and creates (evidence: `backend/controllers/auth.controller.js`)
- Resume Routes → JWT Middleware: protects routes (evidence: `backend/routes/resume.routes.js`)
- Resume Routes → Upload Middleware: parses upload (evidence: `backend/routes/resume.routes.js`)
- Resume Routes → Resume Controller: dispatches (evidence: `backend/routes/resume.routes.js`)
- Resume Controller → Cloudinary Service: uploads PDF (evidence: `backend/controllers/resume.controller.js`)
- Cloudinary Service → Cloudinary: stores asset
- Resume Controller → PDF Service: extracts text (evidence: `backend/controllers/resume.controller.js`)
- Resume Controller → Resume Model: persists and reads (evidence: `backend/controllers/resume.controller.js`)
- Resume Controller → Scoring Queue: enqueues job (evidence: `backend/controllers/resume.controller.js`)
- Resume Model → PostgreSQL: queries (evidence: `backend/db/models/resume.model.js`)
- Scoring Queue → Redis Connection: uses connection (evidence: `backend/queues/scoring.queue.js`)
- Scoring Worker → Redis Connection: connects (evidence: `backend/workers/scoring.worker.js`)
- Scoring Worker → Resume Model: loads and updates (evidence: `backend/workers/scoring.worker.js`)
- Scoring Worker → PostgreSQL: loads resume (evidence: `backend/workers/scoring.worker.js`)
- Scoring Worker → Scoring Service: scores resume (evidence: `backend/workers/scoring.worker.js`)
- Scoring Service → Feedback Cache: checks and writes (evidence: `backend/services/scoring.service.js`)
- Scoring Worker → PDF Service: builds preview URL (evidence: `backend/workers/scoring.worker.js`)
