Technical notes on migrating from Zola to WordPress

I think the series of steps outlined below would probably apply to any migration from a static site generator to WordPress, but your milage may vary! Feel free to reach out if you have any questions about any of these steps.

Step 1. Get WordPress to work for you

I spent a lot of time thinking about the WordPress setup that would work best for me. My biggest goals were:

  1. Largely, to set and forget it, and not have to do a great deal of maintenance
  2. To be able to edit posts from my phone
  3. To replicate the theme + color pallet that I’ve been using more and more across the web
  4. To not spend a lot of money

So, at the end of the day, I figured the best option was to just do something I’m familiar with, which is to prop up a DigitalOcean droplet specifically for this purpose and write the WordPress theme myself.

Step 1a. Server setup

DigitalOcean has a one-click install button to spin up a droplet with WordPress on a LAMP stack — I actually think this is really neat for folks that already know what they’re doing, because it saved me the fifteen minutes of copying and pasting commands from the first page I found when searching for "wordpress ubuntu setup" and then twiddling my thumbs as things ran. If you’re not that experienced with the LAMP stack, I’d recommend that you do that "copy and paste commands from some article" process anyway in order to learn what each piece of the puzzle is in order to be able to easily repair it if things go wrong. Or don’t, if you don’t want to!

Step 1b. Theming

I didn’t want to use some out of the box theme, because I didn’t want the site to feel too "wordpressy"; it’s easy to get caught in a trap of looking and feeling like every other site out there if the building blocks you start from are too restrictive.

I collided the blankslate WordPress theme with the theme I’ve been slapping onto a few other sites to start, and then kind of massaged things until I thought they looked right. There were a few features (like that category bar at the top) that I had to write some custom PHP for — it was a little fun to dust off the language that I used to use every day but, at time of writing, have maybe touched once or twice in two years.

Step 2. Migrating content

Okay. So a page in a Zola site is comprised of a YAML header, surrounded by lines of +++ to wall it off, and then markdown. So really, all I had to do was:

  1. Grab the metadata
  2. Transform the markdown into HTML
  3. Determine the target category for the page
  4. Dump it into WordPress

This took astonishingly little time. At time of writing, my quick-and-hacky script to do this isn’t on Github, because it was so tailored to my experience that I don’t think it would be useful for anyone else to look at — I basically modified the script in a sequence of directories, changing the target category in the script directly before each run.

I used the WordPress basic auth plugin, which was very straight-forward to set up, even if it isn’t in the WordPress plugin directory in order to discourage its use. I use a .dev domain, so I had to have TLS set up from the get-go anyway, and now-a-days setting up HTTPS takes on the order of seconds.

The biggest complication here is that some of my pages used custom templates in Zola. (There’s one example in this post.) Some of these templates were only used once or twice, so I just manually went in and replaced them with their equivalent HTML, but I use Spotify embeds all over the place here, so I just wrote a pretty simple regex find-and-replace that ran at the same time as step 2 in that above migration checklist.

Step 3. Routing

Next, of course, is making sure links to the old sites still worked. I think this is the step that I had to spend the most time thinking about, but at the end of the day, the answer was really straight-forward:

First, I just needed two lists: all of the old paths, and all of the new paths. I wrote a quick script to be able to enumerate these and did a combination of automatic and manual massaging to make a CSV. I only had a little over 100 posts to move, but I think even with a larger volume, it would have been the same amount of work, since you can identify chunks of posts that all follow the same pattern and write like two lines in your favorite scripting language to zip them up.

I decided to use the Redirection plugin, since I wanted to have a UI to manage the redirects, but you could just as easily do this at your server layer.

Then all that was left was to update three domains and wait for things to propagate!

Step 4. Updating old tools, writing new ones

At time of writing, this is actually a work in progress, but I plan to write some wrappers for tools that already exist to help me put articles together, like the roundup generator, for example. The previous workflow was to pipe the output of that program into a markdown file, edit it if necessary, and push it up to github and let the CI job rebuild the site; now, I intend to run a script that will create a draft in WordPress and open it up for me so that I just need to review it and click "publish!"