Jon Allured

Computer Programmer, Whiskey Drinker, Comic Book Reader

Migrating Back to Jekyll

published 10/17/25

This week I finished a migration of the blog back to Jekyll and wanted to write up a few things about that process and the motivation.

Back and Forth

The initial commit for this blog was in May of 2011. At that time I was building the blog using Jekyll and it wasn't until a few years later that I learned of the Middleman project. I ended up deciding to migrate the blog over to Middleman and away from Jekyll. That switch happened in March of 2014.

I don't fully remember my reasons for switching to Middleman but I know that we were using it at Hashrocket and it used Haml and Sass by default which was my preference. Another very superficial thing was that I always thought the underscore folders in Jekyll were really ugly and Middleman didn't do that.

Quick aside here in case that doesn't mean anything to you: Jekyll uses a convention that folders starting with an underscore are treated a bit differently. All other folders are processed and built into the site. So these underscore folders are where you put things like your layout files or include snippets. I always thought that was dumb and that Middleman did a smarter thing but pulling out those types of things into a different location in the project.

Middleman Lost Momentum

Over the years I noticed issues with the health of the Middleman project. As far as I could tell it seemed like there was really just one person keeping it going and they were pretty overwhelmed. I just looked and there is still a 5.x branch that has been unreleased since around 2019.

I've pondered getting involved to help with Middleman but when I'm honest with myself then I know that I would not actually have the time. So the project lacks momentum and I can't be bothered to help which leads to the conclusion that I should just move on to Jekyll which is better supported.

Methodology

Great so there's some thoughts and feelings about how I got where I was and why I wanted to migrate back to Jekyll. Now for the part you probably care about - how did I approach it. Well honestly how I approached it was to have a bunch of enthusiasm, make progress and then forget all about it for like 9 months. Then I wanted to post something on the site, noticed with embarrassment how I had left things and promised myself I would actually finish.

Oops more feelings came out! Back to the technical details.

New Branch and Start Over Commit

The first thing I did was create a new branch and then do a commit that removed everything from the repo except the .git folder. This made the repo empty and allowed me to run the jekyll new command to get a skeleton landed. I messed around with that a few times to get the new command just right and to figure out what I wanted from the skeleton. At this point the project was literally 5 files.

I continued tinkering with the config file and reading through the docs until I figured out sorta what I wanted. I actually ended up making the decision to drop Sass and build the CSS from scratch.

Getting Organized

Let's do a quick digression here so I can describe how I got myself organized to switch between the old Middleman version of the site and the work-in-progress Jekyll version. What I did was create a new folder called blog-migration and then cloned the repo twice inside there to get a structure like this:

code/
  blog-migration/
    jekyll-jonallured.com/
    mm-jonallured.com/

And then the jekyll-jonallured.com/ folder would be on the migration branch while the mm-jonallured.com folder would be on main.

If I had this to do over again I would have used git worktrees. I didn't know much about them at the time but in our new world of AI coding agents I have used them a bunch and this would have been a perfect use-case.

A Test of Correctness

In order to have confidence that I was correctly migrating sections of the site over to the new Jekyll way of doing things I stumbled upon the idea of installing RSpec and writing a test for correctness.

The idea was to use fd on the jekyll-jonallured.com and mm-jonallured.com folders and then compare the results. Something like this:

it "builds the same number of files" do
  fd_command = "fd . build --type file"

  mm_output = `cd ../mm-jonallured.com/ && #{fd_command}`
  mm_matches = mm_output.split("\n")

  system "rm -rf build && bundle exec jekyll build"
  jekyll_output = `#{fd_command}`
  jekyll_matches = jekyll_output.split("\n")

  expect(jekyll_matches).to match_array mm_matches
end

The idea is to formulate an fd command that I run twice and use RSpec's array matcher to compare what comes back. I ran this over and over while tinkering with various configurations and could use the RSpec failure output to drive towards green and a correctly migrated site in terms of files on disk.

Matching Visual Style

Having the right number of files and the right filenames was a nice milestone to hit but when I started a Jekyll server and looked at the site it was garbage. As I mentioned, I had the idea that I should drop Sass and just re-write the style of the site by hand. When I looked at the Sass code what I saw was that I was using 2 main features:

But it turns out modern CSS includes both of these things and browser support is there! Here's some docs:

So I had my Jekyll server running in watch mode, my Sass version of the styles as a reference and I just got to work authoring plain old CSS. It was not hard.

Comparing Generated HTML

As I was making progress on the migration I had the idea that I should actually compare the generated HTML from both sites to get a sense of how closely I was matching there. I went back to my RSpec file and added one for just the index.html page. Something like this:

it "has the same index content" do
  script = <<-SHELL
    bundle exec jekyll build
    rm -rf diff
    mkdir diff
    cp build/index.html diff/jekyll-index.html
    cp ../mm-jonallured.com/build/index.html diff/mm-index.html
    npx prettier diff --write
  SHELL

  script.split("\n").compact.each do |command|
    system(command)
  end

  diff_brief = `diff diff/jekyll-index.html diff/mm-index.html --brief`
  expect(diff_brief).to eq "foo"
end

What this does is build the Jekyll site, copy over the index file, grab the index file from the Middleman version and then run Prettier on them to iron out any formatting inconsistencies. Then I diff the 2 files and see what comes up. In this version of the test I was passing the brief flag to diff which causes it to just print a message when the files differ rather than the actually differences. I played with this command while comparing the 2 and sometimes wrote the diff to stdout or to a file depending on what I wanted to investigate.

Ultimately the differences were trivial and this was mostly just an exercise in making me feel like I didn't miss anything. It did help me tweak my Kramdown config a bit since that translation wasn't quite doing what I wanted. For instance I don't like curly quotes on a technical website so I turned that all off.

I thought that I might do this comparison on all the pages of the site but it was such a pain in the butt that I ended up deciding that this was good enough and I should stop stalling and move on.

Migrating Ruby Code

At this point the content of the site was migrated. What I had left was a bunch of Ruby code that I had written over the years to automate various things. I had scripts to generate a new blog post or create a social image for sharing on social media sites. There were scripts with code for generating my list of the RSS feeds I read and the Podcasts I listen to.

I confess I fell down a rabbit hole here. It would have been fine to create some follow up issues on GitHub for this stuff and complete the migration without this stuff. But my scripts!

Instead what I did was move this code over and refactor it a bunch. I wrote snapshot-style tests for the scripts and code that generate new posts and just way over-engineered it. It was fun but slowed me down.

Stop Stalling

I literally wrote "STOP STALLING" on my whiteboard and then made a list of what was needed to actually ship this migration. Anything that could be a follow up I added as a GitHub issue and ignored. I got the site to deploy locally and then opened the PR to merge the migration to main. It was done!

Ahh Now I Can Write

At this point I have the site deploying main automatically via CI and all that's left on my list are nice-to-haves. This write-up captures the process and now I can finally just get to actually using this blog to publish some posts. At least that's what I tell myself!