🧠 The PDF That Fought Back:
How I Built and Deployed a Narrative Resume Rewriter with GPT, Next.js, and a Very Grumpy TypeScript Compiler
🧠 The PDF That Fought Back:
How I Built and Deployed a Narrative Resume Rewriter with GPT, Next.js, and a Very Grumpy TypeScript Compiler
TL;DR:
In between 60-hour workweeks at my full-time job, I built a tool that rewrites resumes into structured 3-act stories using GPT-4. I had no cofounder — just AI and a will to ship. Along the way, I fought PDF parsing chaos, TypeScript errors that refused to die, and UX pivots that made the product 10x better.
ACT I — The Idea
This started with a deceptively simple concept:
Upload your resume → get a 3-act narrative built by GPT.
Tailor the tone based on personality and style sliders.
Copy it. Share it. Use it.
I’ve reviewed a lot of resumes in my time, and most of them feel… dry. Even the best ones lack story. So I wanted to give people a way to rewrite their experience as a narrative, not a bullet list.
I had no time. I had no frontend cofounder. I had a demanding job.
But I had GPT… and enough stubbornness to try anyway.
ACT II — The Resume Fights Back
The first thing I needed? Text from a PDF resume. That should be easy, right?
Spoiler: it was not.
❌ Attempt 1: pdfjs-dist
Needed worker threads
Didn’t work on Vercel
TypeScript hated it
→ Burned a few hours.
❌ Attempt 2: pdf2json
Promising at first
Turned out it couldn’t handle modern PDFs (no real text layer)
Returned… nothing
✅ Final win: pdf-parse
Pure Node, no workers
Just one catch: no type declarations
I had to write a pdf-parse.d.ts
file by hand and update my tsconfig
just to make the build pass. I also had to do the same for formidable
— the popular file upload library — because TypeScript couldn’t make up its mind about default vs named exports.
🧠 Lesson: Don’t fight TypeScript — bribe it with custom types.
ACT III — The UI Evolves
At first, the UI was minimal:
Resume upload
Textarea
One slider for GPT temperature
But it felt… flat. It didn’t reflect the personality I wanted the tool to help surface.
So I added:
✅ Personality Sliders
Like “Introverted ↔ Extroverted” and “Practical ↔ Imaginative”
These helped GPT understand who the resume is about.
✅ Narrative Tone Sliders
Like “Structured ↔ Spontaneous” and “Reserved ↔ Expressive”
These controlled how GPT rewrote the resume.
✅ Shareable Copy Button
Instant copy of the narrative for easy pasting anywhere
✅ Dynamic Button Logic
First-time click: “Rewrite It”
Already rewritten? Show “Regenerate”
🤖 AI Was My Cofounder
I used GPT-4 not just for the resume rewriting — but for building the tool itself.
It helped me:
Debug import mismatches between
formidable
,pdf-parse
, and Next.jsResolve TypeScript errors about
keyof typeof
and function typingRestructure slider state into generic types
Draft the backend prompt logic for GPT
Real talk: this tool was built by me and AI — nights and weekends, in between a 60-hour workweek.
No excuses. No full-stack partner. Just a goal and a persistent loop of try → fail → fix → ship.
✅ The Final Product
🚀 Live: https://resume-rewriter.vercel.app/
💾 GitHub: https://github.com/KenRambo/resume-rewriter
⚡ Stack:
Next.js 15 (App Router)
Tailwind + ShadCN UI
OpenAI GPT-4 API
Vercel for deployment
⚠️ What Bit Me
ESLint rules in Next 15 are brutal: no
any
, noFunction
, no mercyVercel fails silently on invalid
.d.ts
typingMany PDFs don’t have real text layers (designers, I’m looking at you)
You need
keyof typeof object
tricks to use dynamic keys in TypeScript with state
🧪 What I’d Do Differently
Save rewrites to Supabase and generate unique shareable slugs
Add dark mode and PDF download
Use
@vercel/ai
or server actions for GPT integrationAdd GPT autofill for missing resume data
✨ What You Can Do Now
Upload your resume and see it rewritten like a story
Customize the tone with sliders
Copy the final narrative with one click
https://resume-rewriter.vercel.app/
If you're building anything with AI — remember:
You don’t need 100 hours. You need a clear idea, some grit, and a robot that writes typesafe code.