I’m a software engineer and tech enthusiast. When I’m not working on projects, you can usually find me spending time outside. I’ve learned a lot from others sharing content online over the last 3 decades and am hopeful this site could be useful to others.
How this Site Works
Static site generators were such a great idea. I remember the days of running Drupal (and constantly updating it for security issues) and wanted something simple, fast, and lightweight.
- Hugo Static Site Generator - Simple and fast engine to generate the site.
- Hugo PaperMod Theme - A nice simple and lightweight blog theme.
- Self-hosted Forgejo Repo - Private Git repository to store and version the content, theme, etc.
- Cloudflare Pages - Infrastructure to serve both staging and production content as changes are committed.
- Forgejo Runner - Workflow action to execute Hugo and deploy the output to Cloudflare Pages on Git commits.
Loading the site with an empty cache requires 4 HTTP requests and ~10KB over the network. 😁
Analytics
It is nice to get some high-level statistics for page views, browser metrics, geographies, etc. This site uses Umami to give some basic website metrics without any cookies, cross-site tracking, personal data collection, etc.
Commenting (retired)
When I first started the site I set up Giscus App as a commenting system powered by GitHub discussions. There wasn’t a single comment in the first 9 months so I’ve turned it off.
Build Script
If you host your Hugo site on GitHub, I’d suggest using the built-in Cloudlare build tools. If you host your Git repo locally, this Forgejo Runner script is pretty reusable.
Click here to view the Forgejo runner build script …
name: Build and Deploy Hugo Site
on:
push:
branches:
- main # main branch goes to production
- develop # develop branch goes to staging
jobs:
build-and-deploy:
runs-on: docker # This should match your runner tags
env:
GO_VERSION: "1.25.6"
HUGO_VERSION: "0.154.5"
CLOUDFLARE_ACCOUNT_ID: "<ACCOUNT ID>"
PROJECT_NAME: "<PROJECT NAME>"
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: true
fetch-depth: 0
# Check if we have a cache of our go + hugo versions - this saves ~90% of build time
- name: Cache binaries
id: cache-go-hugo
uses: actions/cache@v4
with:
path: |
~/go/bin
~/go/pkg/mod
key: ${{ runner.os }}-go-${{ env.GO_VERSION }}-$hugo-{{ env.HUGO_VERSION }}
# If there was no cache, install Go and Hugo
- name: Setup Go
if: steps.cache-go-hugo.outputs.cache-hit != 'true'
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
- name: Install Hugo
if: steps.cache-go-hugo.outputs.cache-hit != 'true'
run: go install -tags extended github.com/gohugoio/hugo@v${{ env.HUGO_VERSION }}
# Build the site
- name: Build
env:
CF_PAGES_BRANCH: ${{ github.ref_name }}
run: |
PATH=$HOME/go/bin:$PATH
if [ "$CF_PAGES_BRANCH" == "main" ]; then
hugo --gc --minify --environment production
else
hugo --gc --environment development
fi
# Deploy the site
- name: Deploy
uses: https://github.com/cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ env.CLOUDFLARE_ACCOUNT_ID }}
command: pages deploy public --project-name=${{ env.PROJECT_NAME }} --branch=${{ github.ref_name }}