About this site
This post is a bit meta — I'm going to walk through how I built this site and the thinking behind it. The main thing I wanted to solve was keeping my web resume and a print-friendly PDF in sync without maintaining two separate versions of everything.
One source of truth
All my resume and site content lives in the _data directory. The main file is _data/author.json, where I keep my name, title, skills, work history, education, certifications, and so on. Both the site's Nunjucks templates and the generated resume markdown pull from this data, so when I update something, I only have to do it in one place. No copy-pasting, no wondering which version is current.
Web and print from the same content
Here's how the three outputs come together:
-
Website — The homepage and resume sections are built by 11ty straight from the
authordata. The layouts and partials in_layoutsand_includeshandle the rendering. -
Markdown resume — I have a file called
resume.txt.njk(withpermalink: /resume.md) that uses the sameauthordata to output a single markdown file at/resume.md. That's what you see linked as "Markdown resume" in the sidebar. -
PDF resume — After the site builds, a script called
generate-pdf.jskicks in. It reads the built_site/resume.md, converts it to HTML with markdown-it, and then uses Puppeteer to print that HTML to a PDF (with some print-specific CSS for page breaks and layout). The end result is a PDF that's always generated from the same markdown, which came from the sameauthor.json. On Netlify, the build command handles all of this — Puppeteer/Chrome runs as part of the deploy, so both the site and the PDF stay up to date automatically.
So the full flow looks like: author data → Nunjucks (site + resume.md) → markdown-it + Puppeteer → PDF. One source of truth, web and print always in sync.
Tech stack (brief overview)
Here's a quick rundown of what I'm using:
- 11ty (Eleventy) — My static site generator. It takes Nunjucks, Markdown, and JSON data as input and spits out HTML (plus that one markdown file used for the PDF).
- Nunjucks — Templating for all the layouts and partials.
- Tailwind CSS — Handles all the styling. I'm using a class-based approach for dark/light theme support via Tailwind's dark mode.
- markdown-it — Used inside
generate-pdf.jsto convert the resume markdown into HTML before Puppeteer gets involved. - Puppeteer — Headless Chrome that renders the HTML and generates the final PDF. Netlify installs Chrome at build time and runs the script as part of
npm run build. - Netlify — Hosting and CI. Every deploy runs the 11ty build followed by the PDF script, so everything stays current.
The blog you're reading right now is part of the same repo. Markdown files in src/blog/ get picked up by 11ty, sorted by date, and rendered with the same base layout and theme. If I want to publish a new post, I just drop a new .md file in src/blog/ with layout: blog.njk, a title, and a date — that's it.