hosting

From Ghost to Gatsby

I migrated this blog from Ghost to a Gatsby-generated static site on Firebase Hosting. But why, and how?

History

Back in April 2016, when I created this blog, I decided to use Ghost as it was available on my hosting provider at the time. It had a nice enough admin interface, with posts written in Markdown. After some problems with the provider (see On the importance of backups), I decided to switch to GCP. Keen to sort it as quickly as possible, rather than getting it set up from scratch I used a Ghost configuration from the Google Cloud Marketplace. It all ran on a single tiny Compute Engine instance, cost me just a few pounds a month, and it got the job done.

Unfortunately, the flip-side of the one-click setup was that I was a bit stuck when it came to maintenance and upgrades. I had never set up HTTPS, never upgraded Ghost (now at version 3.24.0; I was on 0.7.8) and the OS was badly in need of patching. Eventually, I found I was posting so rarely I wondered why I was paying even the small amount it cost me each month.

Fast-forward to 2020. Determined to do something to improve the situation, I first tried to see if I could package my Ghost installation into a container image and run it in Google Cloud Run. The short answer: no – it took too long to start up – and I’d still have had to run a database somewhere, and store content in GCS… all too fiddly.

I then happened across the fact that Gatsby could be used to generate a static site from content authored in Ghost. But I’d still have to run Ghost locally, and the source would still be this local Ghost database and a content directory which I’d have to make sure was backed up, and it would all be a bit fiddly. So, eventually I decided just to use Gatsby on its own.

Implementation

Gatsby is a powerful but rather complicated beast – or, at least, so it seems to me. One of those “simple core, do everything interesting with plugins” frameworks. It seems to be a core Node package (and a CLI) which implement a pipeline of sourcing data, and then exposing the data through GraphQL to page templates written in React to render out to static HTML/JS/CSS files. There are over 2000 plugins that do all sorts of things from providing different data sources (filesystem, various CMSes, Trello… you name it), to helpers for rendering PlantUML diagrams.

Building a site from scratch is a lot of work, so there are a lot of “starter” repos out there. I chose to stick close to my Ghost roots with one of several starters which are ports of Ghost’s default “Casper” theme; specifically scttcper/gatsby-casper.

So, having run the gatsby CLI to create a new site based on the starter, I exported my content from Ghost – which produces a JSON file – and used a script called ghost-to-gatsby to extract my post content from the JSON. (I had to hack the script a bit since it wasn’t finding my images to download, and it didn’t fail gracefully when that happened.)

Next I ran the Gatsby development server and started moving my content across. I had to tweak some of the “front matter” (i.e. page metadata) for each page, but otherwise it wasn’t difficult. Fortunately I only have about a dozen posts, so I did this by hand. (If I’d had a lot more, I’d definitely have wanted to script this.)

Deployment

I used Firebase Hosting because it’s an easy way to host a static site, I can configure my custom domain and get a certificate automatically provisioned & managed, and it lets me configure headers and redirects. It also allows me to route certain paths to Cloud Functions or Cloud Run, though I’m not sure how likely I am to use that.

My code repository is on GitLab at michaelbannister/teadd-static so I configured a GitLab CI pipeline to build the site & deploy it. I probably need to do a bit more refinement, to make sure I can’t easily deploy a broken site, but for now I’m testing locally as I write, so it does the job.

Reflections

The CI build is a good deal slower than I’d like, even with the node_modules directory being cached between builds. I’ll probably just have to learn to put up with that, and as long as I don’t go over my free minutes on GitLab CI, it won’t matter.

I still need to get a comments system added. I might start with the easy option of enabling Disqus, which I had on the old site, but I’ve seen good things about Staticman so I’ll be looking at that, too.

Gatsby is clearly very powerful, but I’m slightly disconcerted by how much of the “wiring” is exposed in the React code that came with my chosen starter. It’s further complicated by the fact that the starter uses Typescript rather than Javascript. I know my way around the Javascript language well enough, but have so far avoided React and GraphQL… and I am very bad at making anything look good with HTML/CSS, so I rely heavily on finding a theme I like and making the smallest necessary tweaks. Perhaps this will be the project that finally gives me a purpose to get to grips with React…


Image credit: Image by Andrew Martin from Pixabay