We’ve all been there. You spend an hour meticulously crafting your resume on a "free" online builder, only to hit a massive "Pay $19.99 to download PDF" button at the very end.
Worse yet, many of these platforms are moving toward subscription models. Why do I need a monthly subscription for a document I update once or twice a year? Is the goal to keep me perpetually job-hunting?
I decided I’d had enough. I wanted a resume that was truly free, private, and lived in my own version control.
The Problem with "Free" Resume Builders
- Paywalled Features: "Free" often means "1-page limit" or "only the boring templates."
- The Download Trap: Seeing your resume is free; owning the PDF is not.
- Privacy: Your professional data is stored on a centralized server you don't control.
-
Tooling Overkill: Even great open-source projects often require
npm, CLIs, or complex build steps just to see a preview.
My Solution: The "Really Free" Resume
I built a simple, zero-tooling web resume template. It follows a "Data-Driven, No-Build" philosophy:
-
Separation of Concerns: All your data lives in a single
resume.jsonfile. - Vanilla Everything: No React, no Tailwind, no Webpack. Just pure HTML5, CSS3, and Vanilla JavaScript.
- Print-First Design: The CSS is optimized specifically for the "Print to PDF" feature built into every modern browser.
- Version Controlled: Since it's just code and JSON, you can host it on GitHub Pages for free and keep your history in Git.
How it Works
The logic is intentionally dead-simple. When you load the page, a small script fetches your resume.json, parses the data, and injects it into the DOM.
1. The Data (resume.json)
You don't touch the HTML structure for updates. You just edit a JSON object:
{
"personalInfo": {
"name": "Jawahar Vignesh",
"title": "Senior Software Engineer"
},
"experience": [...]
}
2. The Delivery
Because modern browsers have strict security (CORS), you can't just double-click index.html to load the JSON. But as developers, we already have the tools to fix this. A simple one-liner serves the project:
# Python
python3 -m http.server 8000
# Node.js
npx serve
3. The "Export"
Forget proprietary PDF generators. Open your browser, hit Ctrl + P, and "Save as PDF." The CSS media queries handle the rest, ensuring margins, fonts, and page breaks are professional and clean.
Why You Should Care
As developers, we value ownership and simplicity. By using a JSON-driven approach:
-
Your data is portable. You can easily transform your
resume.jsonto work with other tools later. - You own the source. No one can ever charge you to "unlock" your own work experience.
- It’s a portfolio piece. It shows you understand the basics—clean code, data structures, and the power of the platform.
Check it out
I've open-sourced the template on GitHub. Feel free to fork it, swap in your details, and never pay for a resume builder again.
Pro Tip: Since this is a zero-tooling, plain HTML/CSS project, it is incredibly easy to tweak using AI IDEs or tools (like Cursor, Windsurf, or Copilot). If you want to change the color scheme, add a new section, or change the layout, just ask the AI to modify the style.css or index.html—it works perfectly because the logic isn't buried under layers of frameworks.
What’s your take? Do you prefer using established tools like JSON Resume, or do you like the "Zero-Tooling" approach of plain HTML/CSS? Let me know in the comments!

Top comments (2)
The "Pay $19.99 to download PDF" bait-and-switch is exactly why I stopped trusting "free" tools online. Your approach nails the root cause — the data should live where the user controls it, period.
One thing I hit when building a browser-only finance planning tool with a similar JSON-driven approach: the
@media printrabbit hole goes deeper than you'd expect.break-inside: avoidbehaves differently in Chrome vs Firefox for nested flex containers — Chrome sometimes ignores it inside grid layouts. I ended up adding explicitpage-break-before: autoon section boundaries as a safety net. Did you run into any cross-browser print quirks with your layout?The CORS workaround with
python3 -m http.serveris practical for devs, but it might trip up less technical users who fork the template. Have you considered embedding the JSON directly as a<script type="application/json">block in the HTML itself? It eliminates the fetch entirely — you lose the clean separation, but gain true double-click-to-open simplicity. Could even keep both modes with a fallback: tryfetch('resume.json'), catch → parse the inline block.Also curious about the "AI IDE" angle you mentioned at the end. Since the structure is so simple, have you thought about flipping the flow — let users paste a LinkedIn export or plain text, and auto-generate the
resume.jsonschema? That would solve the cold-start problem where people stare at an empty JSON file not knowing where to begin.Hi @maxxmini Thanks for the comment.
I did not test printing from different browsers. Most popular browsers have a chromium base. So, I hope it works. But I will try it out on other browsers and see if I can fix any issues that pop up. Thanks for pointing this out.
I am planning to add other features where I add another page where the users can add the information on the browser instead of editing the JSON file in a text editor, and I will consider adding a PDF parser using AI. But this is a basic version for devs, and I am not a FE developer by trade myself. So, updates might be slow in coming.