Build your resume using markdown
March 9, 2025
10 min read
It's that phase of my life again where I'm on the hunt for a new job, so I needed to create a resume to apply for jobs and I traditionally always just used Google Docs. However this process felt really slow and cumbersome since I had to modify my resume to fit every unique job description. I found myself aggressively backspacing every line because my template just felt inflexible.
So instead of giving in to the tyrannical word processor I decided to build a tool that would
- Allow me to just use code to build my resume.
- Not stress over formatting.
- Something I could just run locally.
- Would not make me cry.
I already use Markdown for all my blog posts so I decided to build something that would just leverage Markdown, and after a quick Sonnet 3.5 search I found out this was actually feasible and had a rather straightforward workflow.
The workflow
- Write your resume in markdown and wrap key sections with HTML tags.
- Convert the markdown file to HTML using Pandoc which will render your HTML tags in markdown into actual semantic elements.
- Convert this HTML to PDF.
Project setup
All you need are these two packages: npm i node-pandoc puppeteer
We need node-pandoc
to interface with Pandoc (a universal document converter) and puppeteer
to automate the conversion of HTML to PDF.
*Note: Make sure you have pandoc
installed on your machine, as node-pandoc
depends on the local pandoc
installation.
Installing pandoc should set you up with the pandoc installation.
Markdown to HTML
Start with drafting your resume in markdown and wrapping key sections using HTML tags.
Prepare your CSS stylesheet with base styles in a style.css
file that will then be attached to the HTML file.
We'll create a script called convert.js that holds all our logic to run this conversion.
The snippet below calls pandoc to convert the markdown file to HTML and attach our style.css
styles to our HTML template.
<!-- convert.js -->
import nodePandoc from 'node-pandoc';
// Input Markdown file
const src = './resume.md';
// Pandoc Arguments
const args = '-f markdown -t html5 -s -c style.css -o resume.html';
// Callback function to handle conversion result
const callback = (err, result) => {
if (err) {
console.error('❌ Error:', err);
return;
}
console.log('✅ Resume successfully converted to HTML!');
};
// Call Pandoc to convert Markdown to HTML
nodePandoc(src, args, callback);
Now to test our markdown conversion, you can just run this file using node convert.js
or to make life simple you can just add it to your package.json
"scripts": {
"convert": "node convert.js",
},
So now npm run convert
should output a resume.html
Adjusting styles
If you open the HTML you'll see our style.css
coming into effect. You can adjust the root variables or modify the stylesheet to fit your needs.
Converting HTML to PDF
Once we're happy with our HTML and the styling we need to convert this HTML to PDF using puppeteer. The snippet below spins up puppeteer to convert our HTML to PDF and has some additional properties passed into puppeteer to fit our resume neatly.
<!-- generate-pdf.js -->
import puppeteer from "puppeteer";
import { fileURLToPath } from "url";
import path from "path";
// Define __dirname manually
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
(async () => {
const browser = await puppeteer.launch();
const page = await browser.newPage();
// Set viewport size to match A4 dimensions
await page.setViewport({ width: 794, height: 1123 });
// Load the HTML file
await page.goto(`file://${__dirname}/resume.html`, { waitUntil: "networkidle0" });
// Generate PDF with proper scaling
await page.pdf({
path: "resume.pdf",
format: "A4",
printBackground: true,
margin: { top: "5mm", right: "10mm", bottom: "5mm", left: "10mm" }, // Reduce margins
scale: 0.85, // Scale down content to fit in one page
});
await browser.close();
console.log("📄 PDF generated successfully and now fits one page!");
})();
Again we can add this to our package.json
to run it using npm
"scripts": {
"convert": "node convert.js",
"pdf": "node generate-pdf.js",
},
So now npm run pdf
should output a resume.pdf
Finally you can combine the two commands into one and just run npm run build
to trigger the entire flow.
"scripts": {
"convert": "node convert.js",
"pdf": "node generate-pdf.js",
"build": "npm run convert && npm run pdf"
},
This is how my resume turned out. I now no longer have to wrestle with Google docs and can ship out edits much faster. The source code for this can be found here.
TLDR: Leverage Markdown, Pandoc, and Puppeteer to build some cool shit.