Migrating This Blog From Wordpress to Jekyll

Having recently migrated my blog from over to a self hosted Jekyll based site this post will cover the steps taken to achieve this and why I migrated.

This blog has been on for many years and whilst Wordpress is a capable platform I’ve found it to become a bit stale over recent years. Both creating posts and the latest themes offerings are in my opinion clunky and dated, whereas I keep seeing a lot of nice minimal blog themes for other static site generators like Jekyll. It’s also fair to say that as a developer I wanted more control over my blog posting platform without having the ongoing maintenance headaches of having to self host a complex site (which hosting achieved nicely compared to a self hosted Wordpress site). Therefore I found myself looking for a simple, light, code based solution that I could deploy anywhere and that has a good community behind it, as well as good quality themes which led me quickly to a short list of options of which Jekyll seemed the clear winner. I must admit that finding the Chirpy theme was a big plus for Jekyll as I loved it’s design and functionalities but more about themes later in this post.

Jekyll Static Site Generator

Whilst Jekyll has been around for years it is still relevant and has a large market share among the static site generators, although there are many newer ones that give Jekyll some stiff competition as Jekyll is starting to show its age a bit.

If you’re not aware of Jekyll, then it is basically a static site generator (written in Ruby). It takes your plain text content (usually written in Markdown) and processes it using Liquid templates (a Ruby thing). It then generates a complete, static website that’s ready to be served by web servers like Apache or Nginx or anything really. You write your content in Markdown (optionally using a theme that includes Liquid, HTML, and CSS) and then Jekyll uses layouts to create a static website from your content. The resulting site is then ready for deployment without any dynamic server-side processing. It treats Blogs as first class citizens and supports features like permalinks, categories, pages, posts, and custom layouts. As the output is a static site with pure HTML files you just need to upload those files to your host server. No packages, no installs etc.

You can configure Jekyll to use the same URL format as Wordpress so that your existing URLs are still valid, which is really important for SEO.

Choosing a template

As with all static site generators there are many templates to choose from, but I choose the Chirpy template which states its a ‘minimal, responsive, and feature-rich Jekyll theme for technical writing’.

For more info on the Chirpy template see the demo site, github site and wiki site:

  • Chirpy demo site:
  • Chirpy github site:
  • Chirpy wiki site:

Learning Jekyll

The first step was learning jekyll, and luckily the documentation at URL is good and its easy to learn, plus using a template hides a lot of the complexity of Jekyll anyway.

A good starting place is the official site at

Setting up a local Docker based development environment

The next step was setting up a efficient viable development environment that would enable me to quickly test the site, create posts and modify the theme. I could have installed all the Ruby dependencies on my dev machines but I wanted something more flexible that would allow me to run the site locally whilst not having to install all the dependencies particularly when posting from multiple machines.

As Jekyll is ruby based there is some setup that needs to be done on a new machine if you’re not a regular Ruby developer, however it’s much easier to just use a docker based workflow which is what I did.

Initial Project Setup

To set up the docker based development environment I used the following steps:

First fork from the Chirpy template: as per instrctons in wiki

Next follow the documented steps to run ‘init’ to clean up repo. I found that on Windows I got an node_ENV error so I quickly modified the package.json to add ‘cross env’ package but found that the init script also downloads latest code including the packge.json and so it overwrites changes, so I modified the init script to add a pause before the npm i && npm run build. This little hack got the issue resolved quickly for me:

read -p “update package.json file and press enter to continue”

So I run init again, wait for the pause after getting new files, then I modified the package.json file to add cross-env package dependency

“cross-env”: “^7.0.3”,

Then added the use of cross-env in the npm build command script (in package.json)

“build”: “cross-env NODE_ENV=production npx rollup -c –bundleConfigAsCjs”,

..then continue the script.

Docker Image

The Docker image I chose to use was Bret Fisher’s excellent Docker image.

Building a new site via Docker

Although you dont usually need to build a new site if using a template, its worth building a new fresh site for playing around and learning.

To build a new fresh site via Docker you can do the following:

  • cd to empty directory
  • Run docker run on the docker image passing “new” command and a path to your local folder.

docker run -v /path-to-local-dir/:/site bretfisher/jekyll new .


docker run -v /c/code/jekyllplay/site2:/site bretfisher/jekyll new .

WARNING: If your running in Windows in git bash there is bug which means you’ll need to use double slash for the local path. See: For example //c//code//jekyllplay//site2

docker run -v //path-to-local-dir//must-have-dbl-fwd-slash:/site bretfisher/jekyll new .

To run existing site locally in Docker

To run a existing site locally (e.g. after generating one from initializing the template above) you can do the following:

Its basically a docker run command specifying the ports to use and local folder where the site is…

Docker run command (without bundle caching)

docker run -it -p 4000:4000 -v //c//code//richhewlettcom-blog:/site bretfisher/jekyll-serve

Keep this docker image running and navigate your browser to the specified port (e.g. http://localhost:4000 in this example). Any changes you make to your site code will cause a new build to be generated and served.

Docker run command (faster as using bundle caching)

An improvement to the above is to use bundle caching. As a docker image is immutable after it terminates any bundles that will have been downloaded and cached at startup are lost. To avoid this wasted time every time you run the container you can mount a local folder to be used as the cache location resulting in a faster build as the bundles persist between your docker runs.

In the below example the cache folder in the container (/usr/local/bundle) is mounted to the local folder (/c/temp/jekyll/vendor/bundle).

docker run -it -p 4000:4000 -v=”//c//temp//jekyll//vendor//bundle:/usr/local/bundle” -v //c//code//richhewlettcom-blog:/site bretfisher/jekyll-serve

Migrating Posts From Wordpress

There are several open source tools that you can use to migrate your exisitng posts from Wordpress to Jekyll. The process of migrating posts will vary depending on which tool you use. I found that I had to use a few tools to migrate my posts, and have outlined the steps below.

Firstly I needed to export my blog posts from my Wordpress site. Wordpress provides the ability to export your site as an XML file. For sites use this URL:

There is a list of tools on the Jekyll website at for migrating from numerous blogging platforms including Wordpress.

I used the jekyll-import tool which reads the exported XML file and creates a Jekyll post file in the _posts folder for each blog post, as well as creating some pages and categories etc. It was very easy to use. It also downloaded a lot of the images from the site (but not all). Once it had produced all the files I then copied them over into my new Chirpy based site.

Whilst this saved me a huge amount of time, there were some issues. Firstly the posts are output as HTML files and not Jekyll Markdown files, not the end of the world but I wanted to use Markdown. Secondly not all the images got downloaded for some reason.

As I wanted use Markdown for my posts I needed to convert the HTML files to Markdown. To do this I used a VS Code pluging for HTML to Markdown converter - HTML to Markdown Plugin. I simply highlighted the text and hit convert.

As not all the images were downloaded I decided to use the HTTrack tool to crawl my existing Wordpress site and download all the images. I then copied them over to my new Jekyll site.

I manually modified each post to do the HTML to Markdown conversion and ensure the image URLs were valid and modify any markdown issues. I also tweaked the categories and tags. This took some time but ensured that everything was in order.

Setting Up Comments & Analytics

Once I had my Jekyll site up and running I needed to setup comments and analytics. provided good analytics data and a comments system so I’d been spoilt for quite some time and didn’t want to be without.

For analytics I used google analytics, which I use on all my sites and setting it up in the Chirpy template was as easy as adding my google tag in the sites config file.

For comments the Chirpy template supports Discuss and Giscus. Whilst Discus is popular I really didn’t want to use a paid subscription and the free one displays very annoying adverts. So I went with Giscus, which is a github based discussion system, meaning that comments are stored in a github repo. I have been pleased how easy this was to setup. The downside is that commenters need a GitHub account but I can live with that if it keeps adverts off my site.

Hosting and Deployment

GitHub Pages is an ideal free host for your Jekyll site as its powered by Jekyll and has first class support and guides. Personally I’m a big fan of Netlify and so I host my site there and it was quick and easy to setup as Netlify support Jekyll sites as part of their drag and drop or git based deployments.

On Netlify I needed to add a file in the root containing the required ruby version number for the Netlify build to know what the target ruby version is (./ruby-version). I also needed to add an environment variable called “JEKYLL_ENV” set to a value of “production”.

Summary & Conclusion

Moving over to Jekyll was easy and so far I’m very pleased with the result. The Chirpy template has been great and the Docker based workflow has simplified the setup on my local machines. Hosting on Netlify means that in the future I can look to add some server side functionality to the site as well as make use of pre-production deployments or blue/green deployments.

  • Jekyll Site:
  • theme:
  • Blog Example using theme : blog example:
  • Docker image to use: docker image to use:
  • Docker links: &
This post is licensed under CC BY 4.0 by the author.