I am terrible at word processors / editing so I build my resume with LaTeX templates. I gain a pretty, highly configurable resume, but it can be a pain to modify, build, share, etc. A couple weeks ago someone pointed out to me that I forgot to update my most recent role to reflect a promotion (staff software engineer, yeahh!!). I was not at home and I had to work quite a bit to only change a word in my resume. This has always been a pain to me so I figured, why not set up a CI/CD pipeline to build and publish my resume. These are the steps I took.
Posts for: #Hugo
How Dates Work on This Site
Every page on this site has two dates: Created and Updated. Neither one is maintained by hand. Here’s the full flow.
Creating a new page
New content is created with the new.sh script:
./scripts/new.sh content/thissite/my-page.md
This sources .env for HUGO_IMAGE and SITE_DIR, then runs
hugo new inside the Docker container.
Hugo reads the archetype template at archetypes/default.md:
+++
date = '{{ .Date }}'
draft = true
title = '{{ replace .File.ContentBaseName "-" " " | title }}'
tags = []
+++
At creation time, Hugo substitutes {{ .Date }} with the current
timestamp and writes it into the new file’s front matter. The result
looks like:
Organizing This Site
A reference for how this Hugo site is organized and what configuration options are available.
Sections
Sections are created automatically from the directory tree under content/.
Any directory with an _index.md file becomes a section with its own list
page.
content/
├── _index.md ← home page
├── about/
│ ├── _index.md ← /about/ list page
│ ├── whoami.md
│ └── now.md
├── software/
│ ├── _index.md ← /software/ list page
│ ├── ollama.md
│ └── hugo-setup/ ← page bundle (leaf)
│ ├── index.md
│ └── architecture.svg
└── config/
├── _index.md ← /config/ list page
└── this-file.md
No config changes are needed — Hugo derives sections from the filesystem.
Automatic Dating with Git
Hugo can pull dates from Git history so you never have to update lastmod
by hand.
Enable Git info
# hugo.toml
enableGitInfo = true
Configure front matter date resolution
[frontmatter]
date = [':filename', ':default']
publishDate = [':filename', ':default']
lastmod = [':git', ':fileModTime']
How it works
.Date— tries the filename first (2026-04-03-post.md), then thedatefield in front matter..Lastmod— uses the Git author date of the last commit that touched the file, falling back to filesystem mtime..PublishDate— same resolution chain as.Date.
Filename date formats
Hugo recognizes these patterns:
Setting Up Hugo with Docker
This article is a page bundle (leaf bundle). Notice it lives at
software/hugo-setup/index.md — not hugo-setup.md.
What makes this a page bundle?
The directory structure looks like this:
content/software/hugo-setup/
├── index.md ← this file (the page content)
├── architecture.svg ← co-located resource (image)
└── notes.txt ← co-located resource (data)
Everything in this folder belongs to this page. Hugo treats the sibling
files as page resources accessible via .Resources in templates.
Why use bundles?
- Co-location: images and files live next to the article that uses them,
not in a global
static/folder. - Resource processing: Hugo can resize, crop, and fingerprint bundled images at build time.
- Portability: move or delete the folder and everything travels together.
Using a bundled image
In a template you’d access it with: