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.

Installation

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 http://127.0.0.1:18802/

…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.

Settings

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.

Importing

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.

Themes

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.

Plugins

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.

Usage

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.

Conclusion

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 prose.io 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.