PLS Nexus Talent Intelligence
AI-powered resume analysis backend, built module by module as the first piece of PLS Nexus. Users register, upload a PDF resume, and receive an AI-generated ATS score, strengths, weaknesses, and improvement suggestions.
1 stars · Python · updated Jul 10, 2026
The Problem
Recruiters and hiring teams struggle to efficiently screen large volumes of resumes and pull out meaningful candidate insights.
The Solution
A backend-first SaaS module: users register, log in, upload a PDF resume, and receive an AI-generated analysis (ATS score, strengths, weaknesses, missing keywords, recommended improvements). Built on a layered FastAPI architecture with async SQLAlchemy, Alembic migrations, and Pydantic v2 schemas kept deliberately separate from the ORM models — the entity design (User → Resume → AnalysisReport) and auth pattern are meant to become the reusable template for every future PLS Nexus module.
Architecture
FastAPI + async SQLAlchemy over PostgreSQL, with Alembic for migrations. Core entities: User (1—N) Resume (1—N) AnalysisReport — reports are one-to-many rather than one-to-one so a resume can be re-analyzed without a schema change. JWT auth via python-jose + bcrypt. Resume text is extracted with pypdf and persisted (not just held in memory) so analysis can be re-run without a re-upload. AI analysis calls Google's Gemini API via the google-genai SDK.
Tech Stack
Features
- User registration & JWT-authenticated login
- Protected routes via dependency injection
- Secure PDF resume upload with validation
- Automatic PDF text extraction (persisted, not just in-memory)
- AI-generated resume analysis via Google Gemini: ATS score, strengths, weaknesses, missing keywords, recommended improvements
- Resume management & metadata storage
- Alembic database migrations
- Auto-generated Swagger/OpenAPI docs
- /health endpoint for deploy monitoring
In Progress
Full public documentation (architecture diagram, setup guide, API docs, deployment) — being written once the implementation itself is complete, by design (see the project's own docs/PLANNING.md). Deferred for a later version: refresh tokens, history search, rate limiting, and background job queues.
Engineering Case Study
Research
Before writing any code, the project locked down three things: what "done" means for the MVP, the data model, and the API surface — deliberately deferring refresh tokens, history search, rate limiting, and background job queues to a later version rather than letting scope creep mid-build.
Architecture
Core entities: User (1—N) Resume (1—N) AnalysisReport. Reports are modeled one-to-many against a resume, not one-to-one, on the reasoning that a user may want to re-run analysis on the same resume later — a decision made deliberately at the planning stage because reversing it after the repository layer is already written is a rewrite, not a tweak.
Two architectural rules were set from day one and carried through the build:
- Pydantic v2 schemas kept separate from SQLAlchemy models. Mixing the two is called out directly as the most common FastAPI anti-pattern that makes a codebase unreviewable later.
- Async all the way down. A single route left as
definstead ofasync defwhile calling a blocking DB driver would silently block the event loop under load — so the pattern was decided before the first route was written, not discovered under load later.
Implementation
Resume text is extracted with pypdf on upload and persisted to the database rather than only held in memory, so analysis can be re-run without asking the user to re-upload the same file and without wasting a Gemini API call. AI analysis itself calls Google's Gemini API through the google-genai SDK — chosen explicitly over the older, now-deprecated google-generativeai package.
Lessons
The project's own planning doc puts it directly: recruiters rarely read planning documents, but they judge the artifacts of having done the planning — a clean folder structure, a README that shows the schema was thought through before coding started, and a commit history where the first commit is "chore: project scaffold + planning docs" rather than a single 2,000-line dump. That's the standard this build is being held to, one atomic, revertable commit per step.