HMTL Using Codeship talk

Last week (last week!) I was going to give a quick talk about Codeship at HMTL. However, events conspired against me and I couldn’t attend. And there probably wouldn’t have been time to do it, what with all the other excellent-sounding talks on the bill. But I thought I’d put the slides up anyway: Using Codeship for Continuous Integration and Deployment.

This would work better as a blog post, with details and screenshots and the like. So I’ll write that soon.

The presentation put together using the enticing Reveal.js.

HMTL Vagrant talk

Last year (last year!) I gave a quick talk about Vagrant at HMTL. And then promptly forgot to put the accompanying presentation in a useful location. So, here it is: Vagrant. It’s quite good.

It doesn’t cover some of newer Vagrant features like the Ansible Provisioner, Docker-based environments and Vagrant Cloud but it works as a decent explanation of what Vagrant is and why one might want to consider using it. I think.

The presentation was put together using the entertaining Reveal.js.

The journey is the goal

People commit to all kinds of activities, she said, “for the process, for the memories… The argument that there is nothing tangible at the end of it doesn’t hold sway. There’s nothing to stop me opening old builds and going back to them. Rediscovering your old builds” – and she had once made a crumbling Moroccan city, a town square, a giant floating sphere – “is a massive nostalgia trip. Like opening an old photo album.”

Maria Bovor, Minecraft: here’s one I made earlier | The Guardian

I keep forgetting that the journey, play, living, is the goal. I have nothing tangible after going for a walk, but I still do it. Why should any other activity be different?


I’ve been arguing with myself again. Should I use affiliate links when I post here? If I do, should I identify them as such? And if so, how should I make it clear which links are affiliate links and which aren’t? With asterisks? A different link colour? A comment after each? And will people think less of me for trying to earn a few quid when writing about services like FreeAgent*? Will they question my objectivity?

And then I realised: it’s 2014, not 1999. Nobody cares either way. I don’t care. Endless discussions about blogging etiquette don’t really happen any more.

So. Less worrying. More doing.

And affiliate links. Maybe.

* An affiliate link.

Trying out Ghost

A couple of weeks ago I moved this blog from Tumblr to Ghost. I’d wanted to do so since Yahoo acquired Tumblr. I don’t have any trust left in Yahoo after the Flickr fiasco.

I liked the idea of using a simple static site generator (like Assemble, Jekyll or Statamic) instead of a traditional blog engine with a database. Despite Ghost being a young project, enough people have recommended it for me to give it a try. I wanted to see how it measured up against established tools like WordPress, TypePad and Tumblr.


I host with WebFaction. Installation was as simple as creating a new app and mounting it on a new URL. This took all of a minute to do. WebFaction provides version 0.4, the latest release at the time of writing.

While I didn’t try it, a DigitalOcean installation looks similarly straightforward.

By default, Ghost uses an SQLite database to store content. This means that content is stored in a single file on disk, so there’s no need to set up a database, as one would with WordPress. Ghost uses the Bookshelf.js ORM so if SQLite isn’t robust enough, it can be swapped out for a PostgreSQL or MySQL database. I can’t imagine getting enough traffic to bother with this, but knowing it’s possible is reassuring.

Setting up a local version was also quick. I did the following:

  1. Downloaded the files generated during the WebFaction install
  2. Added them to a new local git repository
  3. Edited the development URL in config.js
  4. Ran npm i --production and npm start
  5. Browsed to

…and had a versioned copy of the site on my machine, ready for testing theme changes.

I’ve found setting up a development environment for a WordPress blog unnecessarily difficult. Ghost has separate settings for development and production environments in the Node style. This, coupled with the SQLite option, means creating and moving Ghost environments is pretty easy.

I planned to modify basic settings and make only minor changes to an existing theme, so decided to keep deployment simple and use sftp rather than creating a Grunt task or using CI. I kept forgetting to restart the live Ghost application after uploading changed files. This was annoying but also my fault for taking the lazy route.


Basic Ghost settings are changed in the admin interface, at /ghost/settings/. There aren’t many settings yet, so this only took a minute to sort.

Application settings (blog URL, mail service and database) are changed in the config.js file. I found having settings split between the admin interface and file settings a little odd at first, but there is some logic to it. My guess is that the basic settings can be kept in the database and modified while the Ghost application is running, whereas application settings can either be set for a specific environment or require Ghost to be restarted.

The Ghost admin screen nagged about setting up a third party email provider, even though the default WebFaction install sent email quite happily. I’m susceptible to nagging so decided to fix this. Using Gmail felt fragile and I didn’t want to use my main Amazon AWS account for SES so I went with Mailgun. It took about 20 minutes to create a new Mailgun account, make the required DNS changes and wait for them to propagate. I enjoy faffing with DNS but can see this being a potentially scary process for the sane.


Exporting posts from Tumblr to Ghost did not go smoothly.

There are no proper import tools yet; they’re planned for version 0.5. There is a suggested workaround:

  1. Create a temporary, self-hosted WordPress blog
  2. Export from Tumblr to the temporary WordPress blog
  3. Export from the WordPress blog to a Ghost JSON file
  4. Import the JSON file into Ghost using the hidden debug interface at /ghost/debug/.

The first three steps took a while but did give me a JSON file that looked like it would work. However, importing into Ghost failed, with nothing to indicate why. I edited the JSON so it contained a single post and tried again. Success. But I couldn’t work out what was causing the rest of my archived posts to fail and realised it would probably be faster to manually copy and paste the handful of posts I really wanted to keep, saving the remainder until proper import tools arrive. Sorry, Tim.


I wanted a minimal, well-coded theme. There didn’t seem much point buying a paid theme at the outset, so I tried a few free themes. None seemed as good as Casper (the default Ghost theme) so I stuck with that.

Casper isn’t that flexible, but the markup and styles looked much tidier than any comparable WordPress and Tumblr themes I’ve used. I was pleased to see Handlebars.js used for HTML templating but surprised that Sass, Stylus or LESS hadn’t been used for the CSS, particularly as the Ghost backend uses Sass. It’s probably straightfoward to use a CSS preprocessor to power a theme but I couldn’t establish whether Ghost supports this by default.


There aren’t any.

This isn’t that surprising as they’re not due to arrive until version 0.5, the next significant release. I would have liked URL redirects and working imports (either as plugins or as part of the core) but was actually quite glad to skip the usual plugin-hunting busywork.


Ghost uses Markdown rather than rich text for composition. This is great. I prefer Markdown over the messiness of rich text.

The editing screen has an edit box on the left and a preview on the right. The preview updates in realtime. This is much better than the classic “click to preview” approach and makes writing and editing quite enjoyable.

I had a few minor issues with the interface.

  • The preview uses Ghost core styles. These aren’t easily editable, which causes some disconnect between the preview and published versions. A way to modify or override this stylesheet would be helpful.
  • The most-used icons (“New Post”, “Edit Post” and “Post Settings”) are tiny.
  • The date picker uses a strange date format (eg. 12 Mar 14 @ 09:08) and only accepts dates in this overly fussy style. Allowing a broader range of date types would be nice. To be fair, I only noticed this after manually setting dates on a fair few imported posts.* I can see myself missing the WordPress post search when looking after a blog with many posts.

I also miss the ease of posting with the Tumblr bookmarklet. But then Ghost isn’t quite the same thing as Tumblr and I guess if I really want a bookmarklet I should go ahead and make one.


Ghost feels ready for simple personal blogs. It’s easy to configure, install (on WebFaction and DigitalOcean, at least) and environments are fairly portable. Themes seem cleaner and potentially more flexible than both WordPress and Tumblr themes, partly thanks to Handlebars. I don’t have any plans to work on Ghost, but knowing that it’s built with Node and uses npm for dependency management and Grunt for task running is reassuring. My stuff belongs to me again. I’m enjoying that feeling, after having used Tumblr for 7 years.

I like all these things but I wouldn’t use the current version of Ghost if I were building a blog for someone else, particularly if they’d used WordPress before. It’d be better for me as a developer, but I’d worry that authors would miss features like multiple authors, easy updates and fine-grained control over SEO. The lack of a plugin architecture would mean hacking at the Ghost core to add new features. This doesn’t sound like much fun.

Ghost 0.4 doesn’t give me a great deal more than using a static site generator would, besides a snazzy editor. If I were using an SSG and keeping everything on Github, I’d be able to use an editor on my machine or give a try and wouldn’t have any niggling worries about security.

It’s early days, though. The next major Ghost update may shift this balance in favour of Ghost.


If we believe that machines are ruining mankind, it may be that we are lacking a little in distance and cannot judge the effects of transformations as rapid as those that we have undergone. What are the hundred years of mechanical history when set against the two hundred thousand years of the history of man? We have scarcely begun to settle in this landscape of mines and power stations. Our life in this modern house has only just begun, and the house is not yet even complete.

Antoine de Saint-Exupéry, Wind, Sand and Stars

Happy 25th birthday, Web.


This is what I want to learn: to notice, but not to analyse. To still the part of the brain that’s yammering, ‘My god, what’s that? A stork, a crane, an ibis? – don’t be silly, its just a weird heron.’ Sometimes we have to hush the frantic inner voice that says ‘Don’t be stupid,’ and learn again to look, to listen. You can do the organising and redrafting, the diagnosing and identifying later, but right now, just be open to it, see how it’s tilting nervously into the wind, try to see the colour, the unchancy shape – hold it in your head, bring it home intact.

Kathleen Jamie, Findings