Building ResuPals - A Privacy-First Resume Builder
How I built a fully client-side resume and cover letter builder with friendly mascot characters, focusing on privacy, ATS compliance, and user experience.
When I decided to build a resume builder, the market was already crowded. Dozens of tools promise to help you craft the perfect resume—but they all want something in return: your email, your data, your payment details, often before you've even seen the product.
I wanted to build something different.
The Privacy Problem
Most resume builders operate on a simple model: you create an account, store your resume on their servers, and they have access to some of your most personal professional information. Your work history, skills, salary expectations, and career aspirations—all sitting in someone else's database.
The privacy implications are significant:
- Data breaches - Resume data is valuable for identity theft and social engineering
- Data selling - Your information can be packaged and sold to recruiters, advertisers, or worse
- Vendor lock-in - Your resume is trapped in their format, on their platform
I asked: what if we didn't store any of that?
Client-Side Everything
ResuPals runs entirely in your browser. When you type your work experience, it goes into localStorage—a small database that lives on your device, not mine. When you export to DOCX or PDF, the document generation happens in your browser using jsPDF and docx.js.
// All data stays local
const saveResume = (data: ResumeData) => {
localStorage.setItem('resupals-resume', JSON.stringify(data));
};
// Document generation happens in-browser
const exportDocx = async (resume: ResumeData) => {
const doc = new Document({
sections: [{
children: buildDocxContent(resume)
}]
});
const blob = await Packer.toBlob(doc);
saveAs(blob, 'resume.docx');
};
There's no account creation, no authentication flow, no server-side processing. You open the app and start building. Your data never touches my servers because there aren't any servers handling your data.
Making ATS Happy
A beautiful resume that can't be parsed by Applicant Tracking Systems is useless for most job applications. ATS compliance became a core constraint:
What ATS systems hate:
- Tables and multi-column layouts
- Text boxes and graphics
- Headers and footers containing contact info
- Creative fonts and unusual formatting
- Images embedded in the document
What ATS systems want:
- Simple, linear document flow
- Standard section headers (Education, Experience, Skills)
- Common fonts (Arial, Calibri, Times New Roman)
- Consistent date formats
- Clean plain text extraction
Every template in ResuPals follows these rules. The Polly mascot includes an ATS checker that analyzes your resume and flags potential parsing issues before you submit.
Adding Personality with Mascots
Resume builders are stressful to use. You're often building one because you need a job, which is already an anxious situation. I wanted to soften that experience.
Enter the mascots:
- Resu - A cheerful document with a pencil, guiding resume building
- Cova - A friendly envelope with a heart seal, helping with cover letters
- Polly - A sparkly star with a magic wand, assisting with polish and review
Each has mood states that respond to what you're doing:
type MascotMood = 'happy' | 'focused' | 'encouraging' | 'excited' | 'thinking';
// Mood changes based on context
const getMood = (section: string, progress: number): MascotMood => {
if (progress > 0.8) return 'excited';
if (section === 'work-experience') return 'focused';
if (progress < 0.2) return 'encouraging';
return 'happy';
};
It's a small touch, but it transforms the experience from "filling out a form" to "building something with helpful friends."
The Technical Stack
Next.js 16 with App Router - Server components for the shell, client components for the interactive builder. The landing page is mostly server-rendered for fast initial load.
TipTap - Rich text editing with a schema that outputs clean, ATS-friendly content. The floating toolbar appears on selection for quick formatting without cluttering the interface.
dnd-kit - Drag and drop that feels native. Users can reorder work experiences, education entries, and skills by dragging.
Tailwind CSS 4 - Rapid styling with the new CSS-first configuration. The dark theme with coral accents matches the friendly-but-professional tone.
Lessons Learned
localStorage has limits. The 5MB limit is plenty for resume data, but I had to think about cleanup and data validation. Corrupted localStorage can brick the app if you're not careful.
DOCX generation is complex. The docx.js library is powerful but verbose. Building templates requires understanding Word's XML structure, which has... quirks.
Privacy is a competitive advantage. Users notice when you don't ask for their email. Several early users specifically mentioned choosing ResuPals because they could use it without creating an account.
Mascots require restraint. It's tempting to make them do more—animate constantly, speak in speech bubbles, react to everything. Less is more. They should enhance, not distract.
What's Next
I'm exploring WebLLM for local AI-powered writing suggestions. The model runs in the browser, maintaining the privacy-first principle while adding intelligent assistance. Imagine getting resume feedback without your data ever leaving your device.
The cover letter builder (Cova's domain) needs more guided templates. Cover letters are harder than resumes because they require narrative, and narrative is harder to structure.
And mobile support—because sometimes you need to update your resume from your phone.
Try It
ResuPals is live at resupals.com. No account needed. Your data stays yours.
The source is available on GitHub if you want to see how client-side document generation works or adapt the privacy-first approach for your own projects.