CVTailor
AI-powered CV tailoring that helps job seekers beat ATS systems and land more interviews.

Overview
CVTailor is a full-stack SaaS platform that optimizes resumes for specific job descriptions using AI. Users upload their CV, paste a target job description, and the system produces a tailored version — rewritten to match the role's language, weighted toward ATS keyword compliance, and scored for confidence and compatibility. The platform handles the entire lifecycle: resume parsing, job description analysis, AI-driven tailoring with hallucination safeguards, keyword gap reporting, multi-format export (PDF/DOCX), and subscription billing via Stripe and M-Pesa.
The Problem
ATS Filtering
Most job seekers send the same generic CV to every role. Applicant Tracking Systems filter out ~75% of applications before a human ever reads them. Candidates miss opportunities not because of qualifications, but because their resume doesn't match specific keywords.
Time Drain
Job seekers in competitive European markets submit 50–100+ applications. Manually tailoring a CV per application takes 30–60 minutes — unsustainable at scale. Most candidates also lack the insight to identify which changes will improve ATS rankings.
Bottom line: CVTailor turns a 45-minute manual process into a 30-second automated one — with measurable ATS compatibility scoring.
The Solution
Upload & Parse
Users upload a PDF/DOCX resume or build one using the structured editor. The AI-powered parser extracts structured data (experience, skills, education, certifications) from raw documents.
Analyze & Match
The system embeds both the CV and job description into vector space using AI embeddings, computes a cosine similarity score for semantic matching, and extracts role-critical keywords to identify gaps.
Tailor & Score
The AI rewrites the resume to align with the job description: adjusting bullet points, inserting missing keywords naturally, and matching tone to the seniority level. The output includes a tailored CV, change log, ATS score, and confidence rating.
System Architecture
Data Flow: CV Tailoring Request
- 1User submits: { resume_id, job_description, role_level }
- 2TailoringUseCase checks subscription quota (tailorings_used < tailorings_limit)
- 3Fetches Resume from PostgreSQL (JSONB or file reference)
- 4Stores JobDescription entity with raw text + metadata
- 5If file-based: Fetch from S3 → Send binary to Gemini. If structured: Send JSON to Gemini
- 6Gemini returns: { tailored_resume, changes_made, keyword_analysis, ats_score }
- 7Post-generation validation: structural check, name integrity, company integrity (≥80%)
- 8Store TailoringSession with full diff, scores, and model metadata
- 9Increment subscription usage counter + log audit event
- 10Return tailored CV, change log, keyword gap report, ATS score
Domain Model
| Entity | Purpose |
|---|---|
| User | Auth identity, profile |
| Resume | Structured CV (JSONB), file reference, versions |
| JobDescription | Raw JD text, parsed keywords, company/title |
| TailoringSession | Resume ↔ JD ↔ AI output with scores and diffs |
| Subscription | Usage quotas, tier, billing status |
| AuditLog | Immutable action history per user |
Key Features
AI-Powered CV Parsing
Upload PDF/DOCX and the system extracts structured data using Gemini's multimodal capabilities.
Intelligent CV Tailoring
Rewrites resume content to match the target job description, adjusting tone based on seniority level.
ATS Compatibility Scoring
Generates a 0–100 ATS score with keyword match/miss report and insertion recommendations.
Semantic Match Analysis
Embeds CV and JD into vector space and computes cosine similarity combined with keyword extraction.
Hallucination Detection
Post-generation validation ensures the AI doesn't fabricate experience or change candidate identity.
Multi-Format Export
Export tailored CVs to PDF and DOCX formats with entitlement-gated access per subscription tier.
Dual Payment Processing
Stripe for international cards and M-Pesa STK Push for mobile money users in East Africa.
Resume Version Tracking
Every edit and AI-tailored output is tracked as a version with change summaries and source metadata.
Technical Highlights
Clean Architecture
The Go backend is structured around domain-driven design with strict layer boundaries. Domain interfaces define contracts that infrastructure implementations satisfy — making it straightforward to swap AI providers or storage backends.
Concurrent Embedding Pipeline
The match analysis use case leverages Go's goroutines to fetch embeddings in parallel, halving the latency of the scoring pipeline.
JSONB-First Data Model
Resume data stored as PostgreSQL JSONB, enabling flexible schema evolution without migrations while supporting efficient querying with GIN indexes.
Rate Limiting & Quotas
Per-user rate limiter (60 req/min) at middleware, plus use-case-level subscription quota checks before any AI API call. Resume count includes soft-deleted records.
JWT + Google OAuth
Configurable access (12h) and refresh (7d) tokens. Google OAuth for frictionless onboarding. Input validation via Gin's binding tags.
Secure File Handling
S3 file uploads with 10MB hard cap, CORS whitelisting with multi-origin support, and no-cache headers on API responses.
Challenges & Solutions
The AI would occasionally fabricate work experience entries, invent company names, or change the candidate's name.
Implemented a three-layer validation pipeline: structural check (experience count parity), name integrity (exact match), and company integrity (≥80% match rate). Outputs failing any check are rejected before reaching the user.
Impact
Future Improvements
Async Job Queue
Move AI tailoring to a Redis-backed background worker to avoid HTTP timeout pressure.
Embedding Cache
Store computed embeddings per resume version so repeat analyses skip the embedding step.
Multi-Model Fallback
Route to Gemini by default, fall back to GPT-4o on errors using a circuit-breaker pattern.
Streaming Responses
Use SSE to stream tailored sections as they generate, improving perceived performance.
Resume Templates
Let users choose professional PDF templates using a Go HTML → PDF rendering pipeline.
Batch Tailoring
Submit one resume against multiple JDs in a single request with worker concurrency.
Observability
Add OpenTelemetry tracing with Grafana dashboards for latency percentiles per AI model.
A/B Testing Prompts
Version prompts alongside models and track ATS score distributions to improve quality.
Lessons Learned
AI output is unreliable — validate it
Treating AI responses as untrusted input and adding post-generation validation was the single most important engineering decision.
Clean architecture pays off early
Swapping from OpenAI to Gemini required changing one implementation file. Domain and use cases didn't need a single edit.
JSONB is underrated for evolving schemas
Storing resume data as JSONB let me add new sections without migrations, while still allowing structured Go type assertions.
Quota enforcement belongs in the use-case layer
Checking limits inside the use case (not middleware) means every code path consistently respects the same limits.
Dual payment integration is complex but necessary
Stripe + M-Pesa required separate webhook flows, but eliminated a geographic access barrier for East African users.
Go concurrency shines for I/O-bound work
Running embedding computations in parallel goroutines halved the latency of the match analysis pipeline.
Interested in working together?
I'm open to opportunities in the European tech market.