by Dylan Huang on December 3, 2024
Resume creation is often overcomplicated with clunky word processors and inflexible templates. After 6 years away from the job market (see why), I needed to create a new resume and faced a crucial system design decision: stick with traditional tools like Microsoft Word, or leverage my software engineering experience to build something more robust and portable. I chose to create a solution that is:
After a couple years of blog and documentation content creation, I've never
found something more simple yet flexible as markdown for authoring
content. The separation of content and styling that markdown provides means that
once you figure out the formatting once, you never have to think about it again—you can just focus on writing great content. Previously I've built my resume
using LaTeX and a template (ifykyk),
but after looking back at the source for that resume, I just don't want to dive
back into writing LaTeX. It's great, but not nearly as simple as Markdown. I did
a quick Perplexity
search
which led me to a GitHub repo
showing how to use pandoc to convert Markdown to HTML.
Then you can use one of many HTML to PDF tools along with your own custom .css
file to produce a final PDF. The best part is that you can use CSS to style
every aspect of your resume—from fonts and colors to layout and spacing—giving you complete control over the visual presentation while keeping the
content in simple Markdown.
The entire workflow consists of one shell script to run two commands.
#!/bin/sh
# Generate HTML first
pandoc resume.md -f markdown -t html -c resume-stylesheet.css -s -o resume.html
# Use puppeteer to convert HTML to PDF
node generate-pdf.js
Here is the JavaScript to kick off a headless puppeteer browser to export the HTML to PDF. I chose puppeteer over alternatives like wkhtmltopdf and weasyprint because neither properly respected the CSS I wrote—specifically trying to style the role/company/dates line in the experiences section to be in a single yet evenly spaced row was not possible with wkhtmltopdf, and weasyprint's output styling did not match my CSS either.
const puppeteer = require("puppeteer");
async function generatePDF() {
const browser = await puppeteer.launch();
const page = await browser.newPage();
await page.goto(`file://${process.cwd()}/resume.html`, {
waitUntil: "networkidle0",
});
await page.pdf({
path: "resume.pdf",
format: "A4",
printBackground: true,
preferCSSPageSize: true,
margin: {
top: "1cm",
right: "1cm",
bottom: "1cm",
left: "1cm",
},
});
await browser.close();
}
generatePDF();
Check out the output here and the source markdown
here.
You can also check out the custom .css
file I used
here,
it's simple and classic. I tried not to stray too far away from traditional
resume styling but added a little bit of fundamentals from Refactoring UI,
primarily about visual hierarchy and spacing.