Writing About Migrating from Ghost to Jekyll
In an effort to learn a little about the technology behind today’s blogging platforms, I migrated this blog from Wordpress (php) to Ghost (node.js) at the start of the year. I’ve recently migrated to Jekyll (static content), and this is the story of how I got there.
When I switched away from Wordpress, I found that although Ghost lacked many of the features that Wordpress has by default (or has accumulated through community plugins during its long tenure as ruling blog platform), it was visually refreshing and made the sensible decision of having markdown as its post authoring language.
The migration was an interesting task. The data migration was straightforward as Wordpress offers an export data facility, and Ghost sensibly accepts this an input. At the time, I also switched domains and moved from Apache to Nginx, so the meat of the challenge came in mapping URLs from my old domain to the new without prior experience of Nginx.
An education in Javascript
My blog ran on Ghost 0.4.x throughout this year and it was great. I learned a little about modern javascript through the desire to have custom post and tag paths, which I achieved by hacking about in the Ghost codebase.
Playing around with Ghost inspired me to try other things with javascript. I wrote a node.js application called Ghost Writer that polled my Instagram account and uploaded any photos with a specific tag that weren’t already in the blog to my Imgur account. The final part of Ghost Writer was to publish a blog post, but this was never finished because of the absence of a capable REST API with which to make blog posts.
There were other downsides to Ghost too. Relatively little community support and documentation meant that finding your way around was difficult. No plugins and an incomplete REST API meant that performing tasks other than publishing posts through the admin interface were difficult to achieve. That’s not Ghost’s fault - it’s a young product, but it was frustrating.
Ghost 0.5 was released a couple of weeks ago which offered a lot more stability and a functioning REST API. This sounded great, but I realised they’d changed significant amounts of core code and this would make porting my own customisations really tricky.
I started to think that maybe having to worry about so many moving parts was too much bother for a blog.
Static content
My good friend Jasper had mentioned Jekyll to me before, and I’d heard and ignored various announcements from Github about their Github Pages feature being powered by Jekyll. I knew vaguely it was something to do with hosting a blog statically.
So what is it then? Its website reckons:
Jekyll is a simple, blog-aware, static site generator. It takes a template directory containing raw text files in various formats, runs it through Markdown (or Textile) and Liquid converters, and spits out a complete, ready-to-publish static website suitable for serving with your favorite web server.
“But isn’t adding new posts a hassle without a user interface?” I wondered, “Surely the dominance of Wordpress has proved that the ability to dynamically update blog posts in rich text over the web is integral to posting content?”
It turns out the answer is “not really”. In fact, the security of a web facing UI is probably more concerning to me than the effort of having to create a new file for a post and somehow get it onto my web server. In fact, automating publishing a post from my laptop via scp or git is a trivial exercise, and the fact that I don’t have to have a fairly memory intensive node.js process or a MySQL database running all the time is a big win too.
An education in Python
I spiked my blog in Jekyll by manually creating entries for a couple of pages. I liked how it felt - in particular the absence of a running process, and the fact that I could easily use Jekyll for all pages in the site rather than just the writing section. I decided to migrate the entirety of my blog from Ghost 0.4.2 to Jekyll 2.3.0.
In the spirit of trying new things, I decided to write a migration script in an unfamiliar language. I don’t have much python experience - much less python 3 - so I chose this as the target language for the migration script.
The data for my Ghost blog was stored in a sqlite database, and the data format for a Jekyll blog is a series of markdown files. Python 3 has good native support for sqlite, as well as straightforward string operations and file system access.
The script takes the location of a Ghost sqlite database, reads the post content in batches and creates markdown file equivalents of the posts using a supplied template file. The source and instructions can be found in this gist.
Conclusions
In addition, writing the migration script with Python 3 was a useful exercise. I’ve also made some tweaks to the Soundcloud plugin that I found which adds a bit of Ruby hacking to the mix. I have some plans to add some dynamic content to the “Listening” page, possibly using Angular.js to contact a REST backend that aggregates my listening data from various sites.
Ghost is a very promising blogging platform and I might return to it in the future - I certainly appreciate the experience with Javascript that it inspired me to gain. For now though, this blog is statically generated with Jekyll!