From Medium to GitHub Pages: Why I Made the Move

No paywalls, full ownership, and a developer-friendly workflow

Photo by Mohammad Rahmani on Unsplash

I spent a few years (on and off) writing on Medium. The platform works, it looks good, and it has built-in discovery. But two things kept bothering me: the paywall friction my readers hit, and the fact that every post I wrote was building someone else’s platform, not mine.

For someone who spends their working life thinking about infrastructure resilience and control planes, publishing on someone else’s platform under their terms never sat right. So I migrated everything to GitHub Pages with Hugo as my static site generator.

This is Part 1 of a three-part series. In Part 2 (check back soon), I’ll walk you through the complete technical setup. In Part 3, I’ll share how I evolved the design and workflow.


Why I Left Medium — And Why It Doesn’t Really Matter

Two things mildly bothered me about Medium: readers occasionally hit the paywall, and it always felt slightly odd putting effort into someone else’s platform. Neither was a crisis — I blog occasionally, so I was probably overthinking it.

Then I stumbled across some GitHub Pages blogs in my Chrome feed while doing something unrelated for work. I asked Claude how to host a blog on GitHub, and that was that. Not a careful evaluation — just curiosity and a free evening.

The honest reason I did it: it looked like an interesting challenge, and I learn best by building things. The fact that it’s free, runs on the same Git workflow I use for code, and means I never think about hosting again — that’s the bonus, not the reason.

There are probably better ways to do this — but I’m no expert, and for me that was never the point. The learning was.


The Architecture

The key insight is separating source from output using a two-repository pattern:

Private repo: mcarpendale/blogs          ← Markdown source (nobody sees this)
       ↓  GitHub Action builds Hugo
Public repo: mcarpendale/mcarpendale.github.io  ← Compiled HTML only
       ↓  GitHub Pages serves
https://mcarpendale.github.io

Your writing stays private. Only the compiled website is public. The GitHub Action is the automated bridge—it fires every time you push, builds the site, and deploys it. The whole cycle takes about 30 seconds.


The Tools You Need

Hugo

A static site generator written in Go. It converts Markdown files into a complete HTML website. I chose Hugo over Jekyll (GitHub’s native option) for three reasons:

  1. Speed — Hugo builds are typically 10-50x faster than Jekyll, with even larger gains on big sites
  2. No dependencies — Single binary, no Ruby gems to manage
  3. Active development — Regular releases, modern features

The tradeoff: GitHub doesn’t build Hugo natively, so you need a GitHub Action. But that’s just a YAML file you write once and never touch again.

GitHub Actions

GitHub’s built-in CI/CD system. Free for public repos, and 2,000 minutes/month free for private repos on the Free plan (Pro gets 3,000). Since our Action runs from the private source repo, we draw from this quota — but at ~1 min/build, even daily pushes use only ~30 min/month.

GitHub Pages

Free static site hosting. The magic: name a public repo yourusername.github.io and GitHub automatically serves it as a website at that URL. Minimal configuration in Settings — just enable it and point it at your main branch.


Does It Work?

It does. It’s free, it’s fast, and every change to the blog goes through the same Git workflow I use for everything else. For someone who blogs occasionally and wanted to learn something new in the process, it’s turned out to be a pretty good fit.

That’s really all the justification it needs.


What’s Next

Part 2 covers the complete setup — if you want to follow along, the whole thing takes about 30 minutes and you’ll have a live blog at the end.

In Part 3 I’ll get into how I evolved the design, the draft-versus-published workflow I landed on, and what I’d do differently. Less tutorial, more reflection.

Both coming soon — check back in a little bit.