đź”– Introduction
About the project
PerfectoCV is an AI-powered web application designed to give job seekers a critical advantage in the competitive tech industry. The goal was to solve a major pain point for applicants: getting past automated screening systems (ATS) and creating application materials that stand out to human recruiters.
To address this, I designed and developed a complete, end-to-end solution. The application allows users to upload their resume and a specific job description, then instantly receive an AI-generated analysis. This report identifies missing keywords, provides improvement suggestions, and automatically generates a tailored cover letter and professional LinkedIn follow-up message.
🤔 Problem space
Problems to solve
In today's competitive job market, even highly qualified candidates struggle to get noticed. The hiring process is often automated and impersonal, creating significant challenges for job seekers who need to tailor their applications for every role.
👉 Problem: Resume Rejection by Automated Systems (ATS)
Problem Statement: Most companies use Applicant Tracking Systems (ATS) to scan and filter resumes before they ever reach a human recruiter. A candidate's resume, even if perfect for the role, will be automatically rejected if it doesn't contain the specific keywords and phrases the system is looking for. Job seekers have no reliable way of knowing if their resume is optimized for these systems.
Current solution: Currently, job seekers manually read through job descriptions, trying to identify and sprinkle important keywords into their resumes. This process is slow, inefficient, and often feels like guesswork. Others use basic online word cloud tools which provide a chaotic list of words that lack actionable context, or they pay expensive career coaches for a one-time review, which isn't scalable for multiple job applications.
How do we know it is a problem
Evidence: Industry reports consistently show that up to 75% of resumes are automatically rejected by ATS before reaching a human recruiter.
User Feedback: Online forums and communities for job seekers are filled with posts expressing frustration about the "application black hole," where hundreds of applications yield no response.
Metrics: The primary metric of failure for the current manual solution is a low application-to-interview conversion rate. Candidates spend hours tailoring their resumes with no guarantee of passing the initial automated screening, leading to burnout and missed opportunities.
👉 Problem: The Manual Burden of Customization
Problem Statement: Writing a unique, compelling cover letter for every single application is incredibly time-consuming and mentally draining. This leads many applicants to use generic templates or skip cover letters altogether, missing a key opportunity to stand out and tell their story. The same applies to crafting professional follow-up messages after applying.
Current solution: Job seekers often stare at a blank page, trying to rephrase the same points for different roles. They use generic, one-size-fits-all templates found online which lack personalization and often sound robotic. The process involves manually copying details from their resume and the job description, leading to a document that feels disjointed and takes hours to perfect. For follow-up messages, they either don't send one, or they send a simple, uninspired "Just checking in" email.

How do we know it is a problem
Evidence: Career experts and hiring managers consistently advise that a customized cover letter significantly increases an applicant's chances, yet acknowledge that most candidates fail to do this effectively due to the effort required.
User Feedback: A common sentiment among job seekers is "I hate writing cover letters." They describe the task as their least favorite part of the application process, viewing it as a high-effort, low-reward activity due to the lack of response.
Metrics: The primary metric is time. A user might spend 1-2 hours writing a single cover letter. For someone applying to 10-20 jobs, this becomes a significant time sink that detracts from other job-seeking activities like networking or interview preparation. The high effort leads to a high rate of abandonment for this crucial application step.
👉 Problem: Ineffective Language and Lack of "Wow" Factor
Problem Statement: Many job seekers, especially those early in their careers or non-native English speakers, struggle to write with confidence and impact. Their resumes and cover letters often use passive language ("was responsible for...") instead of powerful action verbs. They fail to quantify their achievements, leaving recruiters guessing about the real-world value they provided in past roles. They know what they did, but they struggle to make it sound impressive.
Current solution: Currently, candidates ask friends or family (who are often not hiring experts) to review their documents. They use grammar tools which are great for catching typos but don't improve the strength or persuasiveness of the content. They might also read blog posts about "power words," but find it difficult to integrate these words naturally into their own experience, often resulting in a resume that sounds awkward or inauthentic.
How do we know it is a problem
Evidence: Hiring managers and career coaches consistently state that the difference between a good resume and a great one is the use of quantifiable achievements and strong, active language.
User Feedback: A common question from job seekers is, "How do I make my resume sound more impressive?" They express a lack of confidence in their writing ability and worry that they are underselling their own accomplishments.
Metrics: A resume with weak, passive language has a lower chance of capturing a recruiter's attention during the average 6-second scan. Improving the language directly increases the "scan-ability" and impact of the resume, leading to a higher likelihood of it being read in full.
Why solve these problems?
Addressing these challenges is critical because the modern job market is defined by high volume and automation, creating a significant power imbalance. Individual applicants are often overwhelmed and outmatched by faceless systems. Solving these problems now is essential because the technology (generative AI) has finally matured to a point where it can provide truly personalized, expert-level assistance, democratizing access to tools that were previously available only to those who could afford expensive career coaches.
Reason 1: To Level the Playing Field. The current hiring landscape heavily favors companies that use automated filtering. PerfectoCV AI empowers individual job seekers, giving them a fighting chance to have their skills and experience fairly evaluated.
Reason 2: To Combat Application Burnout. The sheer effort required to customize applications leads to significant stress and burnout, causing talented candidates to abandon their job search. By simplify the most tedious parts, we can keep candidates motivated and engaged.

Explanation of the Matrix:
Before PerfectoCV: The problems we identified all fall into the "High Importance, Low Satisfaction" quadrant.
Optimizing for ATS is highly important, but user satisfaction with manual methods is extremely low.
Writing custom cover letters is important, but satisfaction with the process is arguably the lowest of all application tasks.
Using impactful language is highly important, but users are not satisfied with their ability to do it well.
The Goal of PerfectoCV: The project's goal is to move all of these critical tasks into the "High Importance, High Satisfaction" quadrant. By making these frustrating but essential tasks fast, easy, and effective, we dramatically increase user satisfaction and confidence, directly improving their job search outcomes.
Goals
Company objective 🎯
đź’ˇ To build the definitive AI-powered platform that empowers job seekers to confidently navigate the automated hiring process and significantly increase their interview call rate.
Project goals
Implement a robust AI-powered analysis engine that accurately parses resumes and job descriptions, identifies keyword gaps, suggest improvements and generates high-quality, context-aware application documents (cover letters and follow-up messages).
Develop a clean, modern, and fully responsive user interface using a consistent design system, ensuring an intuitive and accessible experience across all devices.
Build a secure, scalable SaaS architecture with user authentication (Clerk) and a tiered pricing model (Free and Pro), establishing a foundation for future monetization and growth.
User Stories
User Type: The Job Applicant
Description: The job applicant is actively searching for roles and wants to create the strongest possible application for each job. They expect a tool that can quickly give them an edge over the competition.
🌟 Design space
UI Design
The UI design for PerfectoCV was driven by a philosophy of clean, modern minimalism and user-centric clarity. The goal was to create a friction-less experience that feels professional, trustworthy, and empowering.
The user flow was designed as a logical funnel:
The Homepage acts as a persuasive landing page, guiding the user through a narrative that explains the problem, presents the solution, and provides clear calls-to-action.
The Analyze Page functions as a simple, step-by-step "workbench," removing all distractions and focusing the user on the single task of inputting their data.
The Reports Dashboard provides a clean, card-based overview of all past analyses. Each card gives at-a-glance information, including missing keywords, allowing users to track their history effectively.
The Single Report Page presents the full AI analysis in a clean, scrollable format. It uses a card-based system where each section—such as "Missing Keywords," "Improvement Suggestions," and the generated "Cover Letter", "LinkedIn Followup Message"—is a distinct, collapsible card. This allows the user to focus on one piece of information at a time, creating an organized and digestible experience.
Low-fidelity Wireframes
đź’ˇ Before moving to high-fidelity mockups, I created low-fidelity wireframes to establish the core structure and flow of the application. The focus was entirely on layout and the user journey, ignoring visual design to ensure the fundamental user experience was solid.
The core design concept was to create a clear and logical funnel for the user. I started with a wide, open layout for the marketing homepage to tell a story, narrowed the focus to a single-task "workbench" for the analysis page, and then presented the results in an organized, scrollable report format. Each step was designed to feel like a natural progression from the last.

✍️ Home Page Wireframe
The top-level navigation.
The large Hero Section to grab attention.
The three-part "How It Works" section.
The two-part Pricing section.
The final CTA section.
The Footer.

✍️ Analyze Page Wireframe
simple, single-column layout designed to focus the user entirely on the task of inputting user data.
three stacked content boxes representing the file upload for the resume, the large text area for the job description, and the smaller text area for optional details.

✍️ Report View Page Wireframe
single-column, vertical layout for clarity and mobile-friendliness. It was designed as a series of stacked content cards, with each card representing a key part of the AI feedback.
Each card included space for a title and associated actions (like "Copy All"), ensuring the final design would be both organized and highly functional.

✍️ Reports Dashboard Wireframe
features a card-based grid layout to display all past reports, making them easy to scan. A prominent "+ New Analysis" button was placed in the header as the primary action.
A dedicated space for a "limit warning" was also included to communicate the free plan's restrictions to the user.
High-fidelity mockups
Landing page

đź’ˇ summary of the strategic flow I created for the homepage content
The Hook (Hero Section): I started with a bold, benefit-driven headline like "Turn your resume into a winning application." The goal was to immediately grab the visitor's attention and make a strong promise about the value they would receive.
The Bridge & Proof ("Why PerfectoCV?"): This section was designed to be the core argument. It starts by validating the user's concern ("Generic applications get ignored") and then immediately provides the proof by detailing the core features: Resume Analysis, Cover Letters, and Follow-up Messages. This answers the "Why?" question by directly showing the powerful tools that make up the solution.
The Process ("How It Works"): Once the user understands what the solution is, the next logical step is to show them how easy it is to use. To reduce hesitation, I used a simple, three-step process ("Transform your job application into a winning package") to demonstrate a clear and straightforward path to getting results.
The Offer (Pricing Section): This is where transparently present the cost and features of the different plans ("Basic" vs. "Pro"). By placing it here, the user can evaluate the price after they fully understand the product's value, allowing them to make an informed decision.
The Final Push (Final CTA): concluded with a final, action-oriented Call-to-Action section ("Ready to Land Your Next Interview?") to give the user one last, compelling reason to sign up and get started.
Dynamic Navigation Based on User State

Analyze page

Report View Page

Reports Dashboard Page (initial view)

Reports Dashboard Page (after view)

Development Phase
Technology Stack Selection
đź’ˇ The technology stack for PerfectoCV was chosen to create a modern, scalable, and high-performance application. Each component was selected for its specific strengths in building a full-stack, AI-powered platform, ensuring a seamless development process and a robust end-user experience.
1. Frontend/Backend Framework - Next.js
Why Next.js?
Full-Stack Capabilities: Next.js enabled both the frontend and backend logic to live in a single, cohesive codebase. Its API routes were used to handle server-side tasks like communicating with the AI models and the database.
Server-Side Rendering (SSR) & SEO: For the marketing homepage, SSR ensures fast initial page loads and optimal search engine optimization, which is critical for attracting new users.
Component-Based Architecture: Built on React, it allowed for the creation of reusable UI components, making the application modular, maintainable, and easy to scale.
2. UI Development - Tailwind CSS & ShadCN
Why Tailwind CSS?
Rapid Development: As a utility-first framework, Tailwind allowed for styling components directly in the markup, dramatically speeding up the process of translating design mockups into a fully responsive UI.
Design Consistency: It made it easy to enforce a consistent design language (spacing, fonts, colors) across the entire application without writing custom CSS.Why Tailwind CSS?
Why ShadCN?
Accessible & Unstyled Components: ShadCN provided a collection of beautifully designed, accessible components (like cards, buttons, and dialogs) that are not part of a restrictive library. This gave me complete creative control over the final look and feel while saving significant development time.
3. AI Engine - LangChain.js with OpenAI & Gemini
Why LangChain.js?
Essential AI Orchestration: LangChain served as the "brain" for all AI operations. It simplified the complex process of loading the user's PDF resume, chunking the text, and creating chains of prompts to guide the language models.
Why Use Both OpenAI & Gemini?
Resilience and High Availability: The primary reason for using a multi-model approach was to ensure the application remains highly available and reliable. If one AI service experiences its API usage limit is reached during a high-traffic period, the system is designed to seamlessly switch to the alternate model. This fallback mechanism ensures that the user experience is never interrupted, providing a continuous and robust service at all times.
4. Database - Neon DB (Serverless PostgreSQL)
Why Neon DB?
Power of Postgres, Simplicity of Serverless: It provided the robustness and relational integrity of a traditional PostgreSQL database, which is perfect for storing structured user data, reports, and subscriptions.
Scalability & Cost-Effectiveness: Its serverless architecture means I don't have to manage infrastructure. The database automatically scales with user demand and is highly cost-effective, which is ideal for a new application.
5. Authentication & File Storage
Why Clerk for User Management?
Complete Authentication Solution: Clerk handled all aspects of user authentication—including sign-up, sign-in, session management, and security—out of the box. This saved dozens of hours of development time and provided enterprise-grade security.
Why Uploadthing for File Storage?
High-Level Architecture Diagram
đź’ˇ To visualize the application's structure, I created diagrams for the key services. The system is a full-stack, serverless application where Next.js API routes manage a sophisticated AI pipeline and user lifecycle events. This architecture integrates specialized third-party services to ensure scalability, security, and a robust user experience.

I built a data processing pipeline to handle the core AI analysis. The key feature is a AI fallback mechanism between OpenAI and Gemini. If the primary AI service is unavailable with rate-limits, the system automatically switches to the secondary model, ensuring a seamless and uninterrupted experience for the user.

To synchronize user data between the authentication provider and the application database, I leveraged Clerk's webhook system. When a new user signs up, Clerk sends a secure user.created
event to a dedicated API endpoint. This endpoint verifies the request and then creates a corresponding user record in the NeonDB database, automatically assigning them to the "Basic" subscription plan. This event-driven architecture is highly reliable and ensures data consistency.

For handling paid subscriptions, I implemented an event-driven system using Stripe webhooks. When a user upgrades, Stripe sends a checkout.session.completed
event, which triggers a backend process to update the user's plan to "Pro" in the database. Similarly, a customer.subscription.deleted
event handles cancellations, reverting the user to the basic plan. The frontend UI then reads the user's active subscription status from the database to enforce feature limits, such as allowing 3 analyses per month for Basic users and unlimited analyses for Pro users.
Entity-Extended Relationship Diagram

The database is structured around three primary tables:
User Table: This is the central entity in the system. It stores essential user information and uses the clerk_id
as a unique foreign key to link directly to the Clerk authentication service, ensuring a secure and reliable connection between the application's data and the user's identity.
Reports Table: This table holds all the data generated from an AI analysis. Each record contains the user's inputs (job description, etc.) and the AI's outputs (missing keywords, cover letter).
Subscription Table: This table manages the user's billing and plan status, integrating directly with Stripe. It stores the user's subscription plan type (e.g., "Basic" or "Pro"), their Stripe customer ID, and the current status of their subscription.
Relationship: There is a one-to-many relationship between User
and Subscription
. This allows a user to have a history of multiple subscription records (e.g., subscribing, cancelling, and re-subscribing), while ensuring they have only one active subscription at any given time.
Key Features of the Software
đź’ˇ Here are the core features I implemented in PerfectoCV, along with the key technical decisions and implementation details for each one.
Feature 1: AI-Powered Resume Analysis
This is the core engine of the application. It provides users with data-driven, actionable feedback by intelligently comparing their resume against a specific job description to identify gaps and areas for improvement.
PDF Handling & Data Extraction
Decision: Chose Uploadthing for file handling due to its simple, secure API for managing file uploads within a Next.js environment. For parsing, I selected LangChain.js because of its robust document loaders, which can reliably extract text from various PDF resume formats.
Implementation: The user uploads their resume via the UI, which calls a secure endpoint to store the file using Uploadthing. The file's URL is then passed to a LangChain process that loads and parses the PDF text, preparing it for analysis.
AI-Driven Gap Analysis
Decision: I selected a multi-model strategy (OpenAI & Gemini) to ensure high availability. The primary goal was to provide more than a simple keyword match.
Implementation: I engineered a specific prompt chain that instructs the AI model to:
Identify the core skills and qualifications required by the job description.
Scan the prepared resume text for these keywords.
Generate distinct lists of "Missing Keywords."
Provide qualitative "Improvement Suggestions" based on resume-writing best practices, making the feedback truly actionable.
Feature 2: Automated Document Generation
This feature saves users hours of manual work by automatically generating a complete set of application documents that are context-aware and tailored to the specific job.
Contextual Content Generation
Decision: The AI needed to produce documents that were highly personalized, not generic. Therefore, the implementation needed to provide the AI with the full context of the user's background and the target role.
Implementation: The prompt sent to the AI includes the parsed resume text, the full job description, and any "Additional Details" the user provided. This rich context allows the AI to generate a Custom Cover Letter and a LinkedIn Follow-up Message that are directly relevant to the user and the specific job they are applying for.
User-Friendly Output & Editing
Decision: The generated text needed to be easily accessible and editable. A user should feel in complete control of the final output.
Implementation: The results are displayed in clean, card-based UI components built with ShadCN. Each generated document has "Copy" and "Edit" functions. Additionally, clear "Usage Tips" are provided with each document to guide the user on how to best personalize the content before sending it.
Feature 3: Subscription & User Management System
This feature establishes the SaaS foundation of the application, handling user authentication, payments, and tiered access to features.Authentication & Database Sync
Authentication & Database Sync
Decision: Chose Clerk for authentication to leverage its complete, secure user management system. I used a NeonDB (PostgreSQL) database for its relational integrity.
Implementation: I built a webhook listener (/api/clerk
) that listens for user.created
events from Clerk. When a new user signs up, the webhook triggers a function to create a corresponding user record in the NeonDB database and automatically assigns them the "Basic" subscription plan.
Payment & Feature Gating
Decision: Stripe was chosen for its robust payment processing and developer-friendly webhook system. The application needed to enforce different limits for different plans.
Implementation: A dedicated Stripe webhook handles subscription events. When a checkout.session.completed
event is received, the user's plan is upgraded to "Pro" in the database. The application's backend and UI logic check the user's current plan before allowing an analysis. This system enforces the "3 analyses per month" limit for Basic users while granting unlimited access to Pro users, effectively "gating" the features based on the subscription status.
Challenges Faced and Solutions
Problem: AI Service Reliability and Rate Limiting
The application's core functionality is entirely dependent on third-party AI services (OpenAI and Gemini). If the primary API service experienced downtime or if the application's usage spiked, we would hit API rate limits, causing the analysis feature to fail for users.
Solution: Implemented a Multi-Model AI Fallback System
To ensure high availability and a seamless user experience, I engineered a resilient fallback system
Primary & Secondary Model: In the backend, I configured OpenAI as the primary AI provider for all analysis tasks, with Gemini designated as the hot-standby secondary provider.
Error-Handling Logic: The AI analysis function was wrapped in a try...catch
block. The system first attempts to process every request with the primary model (OpenAI).
Seamless Fallback Mechanism: Inside the catch
block, there is a condition that checks the specific error type. If the error is a 429 rate-limit error
, the system automatically re-sends the exact same request to the secondary model (Gemini). This prevents the system from retrying on client-side errors and makes the fallback more efficient and intelligent.
User Transparency: This entire fallback process is completely invisible to the end-user. From their perspective, they simply receive their report successfully, without any knowledge of backend issues. This creates a robust and reliable service.
Future Vision / next steps
đź’ˇ While PerfectoCV V.1 successfully solves the critical problem of analyzing and tailoring existing application documents, the long-term vision is to evolve it from a reactive analysis tool into a proactive, all-in-one career toolkit.
Long-term vision
Become the Definitive AI Career Co-Pilot: The ultimate goal is to support the user through the entire job search lifecycle, from initial resume creation all the way to interview preparation and beyond.
Data-Driven Job Search Strategy: To provide users with personalized analytics on their application history, helping them understand which skills are in demand for the roles they target and which versions of their resume perform best.