This project is my static portfolio and technical blog, built with Hugo and self-hosted via Docker Compose. It replaces an existing WordPress site with a stack that is:
- simpler to reason about,
- dramatically faster to load,
- and tailored to documenting homelab, networking, security, and automation projects.
Everything that matters—the posts, projects, and about content—is written in Markdown and version-controlled. The final site is just static HTML, CSS, and JS served from a lightweight container instead of a full PHP and database stack.
Project Overview
The goal of this project was to build a single, durable home for my technical work:
- a place to showcase projects and write-ups,
- a portfolio that’s useful to hiring managers and other engineers,
- and an environment that doesn’t break every time a plugin or PHP version changes.
Instead of relying on a dynamic CMS, the site is generated by Hugo and deployed as a static site behind a reverse proxy. The entire setup is orchestrated with Docker Compose, so spinning it up or rebuilding it is as simple as running a single command.
At a high level, the workflow looks like this:
- Write content in Markdown with front matter describing metadata.
- Use Hugo to build the site into a static
public/directory. - Serve those static files from a container (e.g., Nginx) managed by Docker Compose.
- Put the whole thing behind an existing reverse proxy / TLS termination layer.
No database, no application server, no plugin ecosystem to babysit.
Key Features
Static, Content-First Architecture
All pages are generated ahead of time by Hugo. Requests are served directly from static files, which keeps latency low and eliminates entire classes of runtime failures.Profile-Mode Landing Page
The homepage uses a profile-style layout to immediately answer:- who I am,
- what I work on (security, homelab, automation),
- and where to go next (projects, blog posts, resume, contact).
Clear Separation of Content Types
The site is organized into:posts– deeper technical articles,projects– high-level overviews of builds and stacks,about– background, skills, and career context.
Dark-First Visual Design with Clean Typography
The design emphasizes a dark theme with subtle accent colors. Typography and spacing are tuned for long-form technical reading on both desktop and mobile.Tag- and Category-Driven Navigation
Tags (e.g., security, cloud, containers, automation) and categories (e.g., projects, homelab) help group related content so visitors can quickly find posts and projects that match their interests.Zero-Downtime, One-Command Updates
Updating the site is as simple as:- building with
hugo, - reloading or replacing the static files volume used by the web container.
Combined with Docker Compose, the entire environment can be torn down and rebuilt in a repeatable way.
- building with
Technology Stack
Static Site Generator
- Hugo Extended – extremely fast builds, powerful templating, and a straightforward content model.
Theme & UI Layer
- PaperMod – a modern, minimal theme that supports profile mode, good typography, and dark/light modes.
- Customization happens via Hugo configuration and small overrides rather than modifying theme core files, which keeps upgrades manageable.
Content & Filesystem Layout
content/about/– long-form about page and supporting sections.content/posts/– blog-style technical write-ups.content/projects/– portfolio-style project summaries.static/– assets like images.public/– generated static output, ignored in version control and safe to regenerate at any time.
Self-Hosting & Runtime
- Docker Compose manages the containers involved in serving the static site.
- A lightweight web server container (such as Nginx) serves content from the generated
public/directory. - A reverse proxy / TLS terminator in front provides HTTPS, routing, and access control.
Workflow & Tooling
- Local development via
hugo server -Dto preview drafts and layout changes. - Git as the single source of truth for content and configuration.
- Reproducible builds driven by the Hugo CLI and containerized runtime.
- Local development via
Building the Site with Warp
A big part of this project wasn’t just what I built but how I built it. Warp became the central cockpit for everything:
- spinning up Hugo in dev mode,
- tweaking content and config,
- building Docker images,
- and verifying the site end-to-end.
Iterating Quickly on Content and Layout
Most of the day-to-day work looked like this:
- Open Warp with a split view – one pane running
hugo server -D, another ready for Git, Docker, and one-off commands. - Edit content and configuration – adjust front matter, tweak
hugoconfig, reorganize sections. - Watch changes live – Hugo’s live reload, combined with Warp’s block-based terminal, made it easy to see exactly which command produced which logs.
Seeing each hugo run as a distinct block meant I could scroll back through build errors, warnings, and config issues without losing context—especially helpful when tuning paths, permalinks, and theme parameters.
Tight Feedback Loops with AI Assistance
I also leaned on Warp’s AI capabilities during development:
Config exploration:
When I wasn’t sure which Hugo option or PaperMod parameter to reach for, I could draft a rough idea in the config and refine it with AI suggestions until it matched how I wanted the site to behave.Content polishing:
Drafts for project descriptions, tag names, and section wording started as quick notes, then got iterated into something more polished—still in Markdown, still under version control.Troubleshooting:
When something didn’t render the way I expected (wrong taxonomy, missing cover image, odd layout), it was easy to paste the relevant snippets and get targeted fixes without leaving the terminal.
The combination of live builds, structured terminal output, and AI-driven assistance made the development loop feel closer to “pair-programming the site” than fighting with a CMS UI.
From Local Hugo to Docker Compose
Once the site felt solid in hugo server mode, I used Warp to step through the self-hosting side:
- Build the static site with
hugo. - Wire the output directory into a web server container via Docker Compose.
- Bring up the stack, check logs, and verify behavior behind the reverse proxy.
- Iterate on the Compose file, volumes, and environment variables until the containerized version matched what Hugo served locally.
Having all of this in one place—the Git history, Hugo commands, Docker logs, and AI-powered explanations—kept the mental overhead low and the feedback loop tight.
What I Learned
This project ended up teaching me a lot more than “how to use Hugo”:
1. Designing a Sustainable Content Model
I learned how to structure the site so it remains flexible as it grows:
- using sections (
about,posts,projects) to separate content intent, - enforcing consistent front matter for titles, dates, tags, and descriptions,
- and leveraging tags and categories to keep related work discoverable.
The result is a content model that supports both quick project blurbs and long-form deep dives without feeling chaotic.
2. Embracing Static Generation for Reliability
Moving away from a database-backed CMS reinforced the value of static generation:
- upgrades are just new builds,
- rollbacks are just older artifacts,
- and backups are just file copies and Git history.
The biggest lesson: for read-mostly sites, simplicity and predictability are often more valuable than runtime flexibility.
3. Working With an Opinionated Theme, Not Against It
Instead of fighting the theme, I learned to:
- lean into PaperMod’s strengths (profile mode, typography, dark/light handling),
- configure everything I could through Hugo config and partials,
- and reserve customizations for areas that truly needed it, like highlighting certain skills or sections.
This kept the site maintainable while still feeling tailored.
4. Using Warp as a Development “Control Room”
Warp changed how I approach terminal-driven projects:
- Block-based output made long-running logs and repeated builds manageable.
- AI assistance let me treat misconfigurations and odd errors as conversations rather than endless search queries.
- Command-centric workflow encouraged small, reversible steps: tweak config, run Hugo, inspect output, commit.
The key learning here was that the terminal doesn’t have to be just a command runner—it can also be an environment for designing, debugging, and refining a project end-to-end.
5. Treating the Site as an Artifact, Not a Pet System
The combination of Hugo, Docker Compose, and Git pushed me toward treating the site as something I can:
- rebuild from scratch,
- move between hosts,
- and version like any other application.
It’s no longer a vulnerability ridden Wordpress site; it’s a static site.