Jamie Lawrence

Rebuilding the blog in 2023

Can you rebuild your blog without writing a post about it? I guess not.

This site was previously written in Middleman which I really like for its simplicity and, since it’s written in Ruby, I can make it do what I want.


So, since I had something that work, I naturally decided to use something else 🤷‍♂️. Bridgetown is the spiritual successor to Jekyll and Middleman but more actively maintained than either.

Honestly, Middleman was probably fine and I haven’t encountered anything special about Bridgetown. Perhaps Tailwind was easier to setup? If anything, a few things are harder/impossible like filtering out hidden posts from paginated collections, or having annual archive pages which I don’t need to manually create. Perhaps it’s faster? It’s hard to compare because I also switched hosts but with ~900 pages it’s building in 1m 45s in production.

Bridgetown seems like a good choice if you were setting up a new blog as a Ruby developer, particularly if you wanted to stay away from the Javascript-centric platforms that seem over-engineered.

Hugo is also fine though I found it a bit complex and the templating language a bit limited.


I’ve done the themes and Bootstrap stuff for many years and I took a look at them again but none fitted the style I wanted.

I was looking for something clean, minimal, and readable. Something like Medium or Ghost.

Since I didn’t need anything fancy or with many flourishes, I gave TailwindCSS a go. It took a few false starts and figuring out what it was doing, why pasting in examples didn’t always produce the results I wanted etc. After a while I became reasonably productive though the extreme line lengths are a bit of an obstacle. It kinda also requires you to know the CSS properties it’s referencing so figuring out flex-row meant searching for documentation on flex-direction: row; (CSS is not my forte)


When building a new site, it’s often useful to compare the original site with your new version to make sure all the same URLs are working. Ideally we should minimise link rot.

Sitediff has you covered:

sitediff init oldsite.example.com newsite.example.com (write the config file)
sitediff crawl (crawl the old site and cache the data)
sitediff diff (crawl the new site and compare to the cached old site)
sitediff serve (present the results in a browser for filtering/searching)

This will init a sitediff config file locally, crawl the old site, produce a diff of the old site vs new site, and then open a page showing you the results. Useful!

Editing Frontmatter

I’ve been using flat markdown files for a few years since I switched from Wordpress. Back then I did a lot of painful scripting using sed to wrangle the frontmatter attributes. This time I used Ruby and it made things much much easier.

Typically when migrating blog content you need to add new frontmatter attributes, migrate the format of the values, or delete old ones if you’re in a tidying mood. sed makes it possible (though you might die trying) but fmedit makes it easy and reliable.

Here’s the code I wrote to batch process some of the frontmatter

Fmedit::Files.new "src/_posts/*.md" do |file|
  # Exclude from pagination if the posts is hidden & published
  if f.get("hidden") == true && f.get("published") == true
    f.add "exclude_from_pagination", true
  # Remove the hidden property (not used)
  f.remove "hidden"
  # Prefix non-urls image values with /images/
  f.edit "image", /^((?!images\/.+|\/|http).*)$/, "/images/\\1"
  # Prefix image/ values with a leading /
  f.edit "image", /^(images\/.+)$/, "\/\\1"
  # Save the file

Cloudflare Pages.

Use it. There’s no immediate reason not to.

I was previously using Netlify but that was 2017’s choice and it was good to try out Cloudflare’s alternative. It took about 10 minutes to get it working and it’s free. It also appears to build very quickly (1m 45s).

Setting up Cloudflare Pages was just a case of:

  • Add a .node-version file containing 16.16.0 (or any version > 14)
  • Set the BRIDGETOWN_ENV environment variable to production

(blatently stolen from these instructions). You then walk through the instructions in the dashboard: