Behind the blog
Table of contents
When I started writing here about five years ago, I made a promise to myself that I wouldn’t give in to the trend of starting a blog, adding one overly enthusiastic entry about the stack behind it, and then vanishing into the ether.
I was somewhat successful at that and wanted to write something I can link to when people are curious about the machinery that drives this site. The good thing is that the tech stack is simple and has remained stable over the years since I’ve only made changes when absolutely necessary.
Markdown
I write plain Markdown files in my editor of choice, which has been VSCode since its launch.
Once I’m finished, make format runs the local Markdown cleanup, including prettier
, to
fix line length and formatting.
Hugo
Hugo is the static site generator that turns the Markdown files into HTML. I chose it because I needed something that can build the site quickly, even with lots of content. It lets me hot reload the server and check my changes as I write. Plus, I don’t get to write Go at work, so messing with Hugo templates or its source code gives me a reason to play around with Go.
I initially tried some JS-based SSGs but dropped them pretty quickly because I couldn’t keep up with the constant tooling changes in the JavaScript universe. I use a handrolled theme and have tweaked the CSS over time.
GitHub Issues
I use GitHub Issues to brainstorm ideas and keep track of my writing. I usually gather ideas throughout the week, log them in Issues, and then write something over the weekend. This workflow is heavily inspired by Simon Willison’s blog on his workflow.
![GitHub Issues used as a research notebook]
GitHub Actions and GitHub Pages
Once I push content to the main branch, GitHub Actions automatically runs the checks, builds the site, and deploys it to GitHub Pages . There’s nothing to maintain, and I don’t have to worry about scaling, even if one of my posts hits the front page of Hacker News. Aside from the domain, this site costs me nothing to run, and I plan to keep it that way.
Cloudflare Cache and R2
I’m a huge fan of Cloudflare and often try to shoehorn their offerings into my projects. Since my domain is registered with them, setting up their proxy with my domain’s DNS and turning on caching took just a few minutes. Their caching layer absorbs most of the traffic, and less than 10% of the requests hit the origin server. Plus, having the proxy layer gives me access to more accurate analytics.
![Cloudflare cache analytics dashboard]
Static assets like images, CSS, JS, and other files are stored on Cloudflare R2 . I used to host my images with GitHub Issues and serve CSS and JS from the origin, but I recently switched everything to R2. Now I can manage it all from one place without worrying about costs. Their free plan is super generous - there’s no egress bandwidth fee, and because of caching, I barely use any of the quota. It’s fantastic!
![Cloudflare R2 dashboard]
Oxipng
Oxipng is used to losslessly compress PNG screenshots before uploading them to the Cloudflare R2 bucket with the wrangler CLI. Images are immutable: each uploaded object gets a content hash in the filename and long-lived cache headers, so Cloudflare can serve repeat reads from cache without revalidating R2.
make upload-post-image \
post=content/go/request_coalescing.md \
file=/tmp/singleflight-flow.png \
name=singleflight-flowThis command derives the R2 directory from the post, normalizes names to kebab-case, runs
oxipng -o max --strip safe for PNGs, uploads with
Cache-Control: public, max-age=31536000, immutable, and prints the canonical URL. Most
article images are PNG screenshots, so the default path is screenshot to PNG, lossless max
compression, upload, paste the printed URL into Markdown.
Standard.site records use the same R2-hosted site cover. CI downloads and verifies it before publishing, then commits any generated metadata changes.
Google Analytics
I’m still using Google Analytics , even though I’m not a huge fan. Cloudflare already gives me better traffic insights, but the free version doesn’t show how many hits each page gets. At some point, I might just pay for Cloudflare’s upgraded plan so I can get rid of the bulky, intrusive analytics scripts for good.
The source code and content for this site are all publicly available on GitHub.