Skip to main content

Ben Cromwell

Migrating From Ghost to Hugo

I’ve migrated this blog from Ghost to Hugo. Primarily because it’s updated so infrequently that every time I even thought about maybe writing something (yes, very committal) Ghost would need an update. Most recently, and the final straw, was it got stuck in a dependency loop of needing a Node upgrade but needing a Ghost update first but to do that also needed a Ghost CLI update and that needed a newer version of Node but without the older Ghost CLI installed it couldn’t be upgraded to the point where it could be upgraded or something or something and before you know it you’ve entered a Franz Kafka novel.

There obviously must be a solution but I’d been thinking of switching to Hugo for a while and recently I’ve preferred editing in markdown for writing documentation, using Vale and markdownlint. After a couple of failed attempts at sorting Ghost out I setup Hugo.

Content in markdown is a lot more portable to any other tool in the future than stuck in some database’s format. It being committed gives you your change history and your content is backed up to wherever you keep your Git repos.

To start with, grab a Ghost export from Settings -> Labs. Then I used ghostToHugo to get the content reformatted into markdown files.

As barely anyone reads this it’s fine in the free tier of Cloudflare Pages and that also gives you preview deployments off PRs, which is a nice feature. I changed the A record to a CNAME and setup from their built in Hugo template and it was done in basically no time.

For Cloudflare pages, to avoid potential duplicate content warnings we need to disable access to the *.pages.dev subdomain.

Following that, add to static/_redirects the old blog’s paths:

/:year/:month/:day/:slug/ /posts/:slug 301

And finally, the all-important X-Clacks-Overhead can be added by creating a file at static/_headers:

https://cromwell.dev/*
  X-Clacks-Overhead: GNU Terry Pratchett

These two files are Cloudflare Pages-specific. Hugo copies them over from static on deployment, so they go in static and not the repo’s root directory.

Finally, I added a vale.ini to the repo.

StylesPath = vale-styles  # Location of styles directory
MinAlertLevel = suggestion # Options: suggestion, warning, error

Packages = Hugo, write-good, Readability

Vocab = Custom

[*.md]
BasedOnStyles = Vale, write-good, Readability, Custom
Vale.Repetition = False
Vale.Spelling = False

# tmp
write-good.E-Prime = False
write-good.Passive = False
write-good.ThereIs = False
write-good.TooWordy = False
write-good.Weasel = False

Custom contains a custom dictionary. Things like “PhpStorm” and “Ansible”.

Apparently I need to write more good. Until such a time as that, I can turn off some of the noise it’s generated and eventually (probably never) remove those exclusions and tighten things up. This isn’t documentation after all, a blog is more free and random and flowing. Plus no one’s ever going to read this other than me anyway, whereas I would hope people do read the documentation I write. So it goes.