If you've applied for a tech job recently, you already know the pain: you spend hours crafting the perfect developer resume, tweaking your GitHub links, hit submit, and then... nothing. You get thrown into the Applicant Tracking System (ATS) black hole.
Over 75% of resumes are automatically rejected by bots before human eyes ever see them because of bad formatting or missing exact-match keywords. I got so frustrated by this that I decided to solve it.
I recently launched ATSense, a 100% Free ATS Resume Checker and Builder. It mimics the exact parsing algorithms used by systems like Workday and Greenhouse, scores your resume, and uses AI to fix it.
In this post, I want to break down the technical architecture of how I built it using React, Laravel, and the OpenAI API, and why building an ATS parser is surprisingly difficult.
The Tech Stack
I needed a stack that allowed for lightning-fast frontend interactivity (for the drag-and-drop resume builder) with a highly secure, scalable backend (to handle PDF extraction and API rate limiting).
- Frontend: React, Vite, Tailwind CSS, Lucide Icons
- Backend: Laravel 11 (PHP 8.2), MySQL
- AI Engine: OpenAI GPT-4 API
- Deployment: GitHub Actions CI/CD to cPanel
Challenge 1: The UI and "Guest-First" Architecture
As a developer, I hate signing up for things just to test them. I wanted ATSense to be a "Guest-First" application. You arrive, drop your PDF, and get your score instantly without handing over your email or a credit card.
Because of this, the React frontend handles a lot of heavy lifting. I used Tailwind CSS to build a responsive, two-column "Recruitment Cockpit" where users can view their PDF on one side and the dynamic ATS scoring HUD on the other.
By keeping state management centralized in React, users can tweak their bullet points and watch their ATS Match Score update in real-time.
Challenge 2: Parsing the PDF and The ATS Logic
The hardest part about building an ATS checker is that PDFs are notoriously terrible at preserving text structure. A human sees a cleanly formatted "Experience" section, but a parser might just see a jumbled string of coordinates.
To solve this, the Laravel backend steps in. When a user drops a resume:
-
Extraction: Laravel accepts the
multipart/form-dataupload and extracts the raw text. - Structuring: Using regex and Laravel's elegant collection pipelines, the backend looks for standard ATS headers (e.g., Experience, Education, Skills) to reconstruct the document into a readable JSON schema.
- The Score: We run the extracted data against standard ATS compliance rules. (Are there weird graphics? Are contact details stuck in a header? Are there quantifiable metrics?)
Challenge 3: Injecting AI for Gap Analysis
Knowing your resume failed is only half the battle. I wanted the tool to actually fix it.
When a user drops a Job Description into the UI, Laravel takes the parsed resume JSON and the Job Description and ships them to the OpenAI GPT-4 API using a highly restrictive, low-temperature prompt system.
The AI performs a "Gap Analysis"—it cross-references the hard skills the employer is asking for against what the user actually wrote. It doesn't just tell you that you are missing "React Hooks"; it actually generates a suggested, optimized achievement bullet to insert directly into your resume.
What's Next?
Building the core infrastructure took a lot of late nights, but seeing people finally bypass the dreaded ATS bots makes it worth it.
If you are currently job hunting or just want to see how your resume holds up against the bots, I would love for you to try it out!
👉 Test your resume on the ATSense Grader here
Let me know what you think of the stack, or roast my UX in the comments below! I'd love to hear your feedback.
Top comments (0)