My old site was a single index.html Bootstrap page. No blog, no easy way to add projects, and the resume lived in a completely separate repo. It worked but it was a pain to maintain. So I rebuilt it with Hugo.
Here’s how I did it — and how you can do the same.
What is Hugo
Hugo is a static site generator written in Go. You write content in markdown, define layouts in HTML templates, and Hugo compiles everything into a folder of static files ready to be served from anywhere — GitHub Pages, Netlify, S3, whatever you want.
No runtime, no database, no server to maintain. Just files.
It’s also extremely fast. A full site build typically takes under a second. The dev server live-reloads on every save, so the feedback loop while writing is instant.
Installation
On macOS with Homebrew:
| |
Verify it worked:
Make sure you get the extended version — some themes including PaperMod require it for SCSS processing.
Creating a New Site
This scaffolds the basic folder structure:
Adding the PaperMod Theme
I went with PaperMod — minimal, fast, and well maintained. Add it as a git submodule so it stays in sync with upstream without bloating your repo:
| |
Then tell Hugo to use it in hugo.toml:
When someone clones your repo they’ll need to run this once to pull the theme:
| |
Configuring the Site
PaperMod has a profile mode that works well for a personal site — a landing page with a photo, a subtitle, and buttons to your main sections. Here’s the relevant config:
| |
Put your profile photo at static/img/photo.jpg and it’ll show up on the landing page.
Content Structure
Everything in content/ becomes a page. I organised mine like this:
A new blog post is just a file:
| |
The front matter at the top controls metadata:
Set draft: true while writing, flip it to false when you’re ready to publish.
Custom Template for the Resume
This was the part I was most particular about. I wanted the resume to live as a plain markdown file but render with a proper print layout — clean, full-width, with a Print/Save as PDF button.
Hugo lets you override the theme template for any content type. Create a file at layouts/resume/single.html and Hugo will use it instead of the default template whenever it renders a page with type: resume in its front matter.
The template itself is straightforward — extend the base layout, render the content, add a print button and some CSS:
| |
And in content/resume.md:
Now the resume is just a markdown file. Update it, push, deployed.
Auto-Deploy with GitHub Actions
The deploy workflow lives at .github/workflows/deploy.yml. It triggers on every push to main, installs Hugo, builds the site, and publishes to GitHub Pages:
| |
One thing to set up in your GitHub repo: go to Settings → Pages → Source and switch it from “Deploy from a branch” to “GitHub Actions”. Do this before your first push to main.
After that, every commit to main is a deployment. Takes about a minute.
The Workflow Going Forward
Write a post in markdown, commit, push. That’s the entire loop. No CMS to log into, no build command to remember, no separate deploy step. The friction is low enough that I might actually keep this thing updated.
We’ll see.