All you need

health, social life, job, house, partners, finances; leisure use, leisure amount; working time, education, income, children; food, water, shelter, clothing, sex, health care; mobility; physical safety, social safety, job security, savings account, insurance, disability protection, family leave, vacation; place tenure, a commons; access to wilderness, mountains, ocean; peace, political stability, political input, political satisfaction; air, water, esteem; status, recognition; home, community, neighbors, civil society, sports, the arts; longevity treatments, gender choice; the opportunity to become more what you are that’s all you need

Kim Stanley Robinson, 2312


A quote in an article by Oliver Burkeman caught my eye a while back:

Eyal urges businesses to think ethically. (Creating addictive products you wouldn’t use yourself, he says, “is called exploitation”.)

I tracked down the original quote to Nir Eyal’s 2012 post, The Morality of Manipulation:

Creating a product that the designer does not believe improves the user’s life and which the maker would not use is exploitation.

Obvious, but easy to forget: a handy lodestar.

Invisible machines

The more perfect machines become, the more they are invisible behind their function. It seems that all man’s industrial effort, all his calculations and his nights spent poring over drawings, all these visible signs have as their sole end the achievement of simplicity. It is as if only the experimentation of several generations can define the curve of a column or a ship’s hull or an aeroplane fuselage, and give it the ultimate, elementary purity of the curve of a breast or a shoulder. On the surface it seems that the work of engineers, designers and research mathematicians consists only in polishing and refining, easing this joint and balancing that wing until there is no longer a wing joined visibly to a fuselage, but a perfectly developed form freed at last from its matrix, a spontaneous and mysterious whole with the unified quality of a poem. It seems that perfection is attained not when there is nothing more to add, but when there is nothing more to take away. At the climax of its evolution, the machine conceals itself entirely.

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

Codeship and curly bracket expansion

This isn’t an issue with Codeship as such, but it can affect it.

I had a task in an npm script that created some directories for a couple of cli tools that (for whatever reason) expected directories to be present but wouldn’t create them:

"copy": "mkdir -p dist/{dir1,dir2}",

This task worked locally (on OS X El Capitan) but the first time I tried to build on Codeship, my tests failed.

Working out why was pretty straightforward. Codeship images use Ubuntu. Ubuntu uses dash rather than bash for /bin/sh

$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Feb 19 2014 /bin/sh -> dash

…and of course, dash doesn’t support curly bracket expansion. Huh. Who knew?

There wasn’t much point spending time on such a simple line, so I went with the cheap fix of listing out each mkdir in long form:

"copy": "mkdir -p dist/dir1 && mkdir -p dist/dir2",

I need to remember that:

  1. Avoiding fancy stuff is sensible (curly bracket expansion isn’t particularly fancy, but it wasn’t exactly saving me a great deal of effort, either).
  2. Subtle cross-platform issues crop up all over the place. Using Vagrant, Docker or Otto for consistent development, stage, CI and production environments is a good idea where time allows.
  3. Running tests on a range of platforms is worthwhile. Time to get up and running with Appveyor, I think.

I like using npm as a build tool, but keep coming across niggling issues like this.

Continuous deployment of static sites from Codeship to WebFaction with rsync

Mmm, that’s a a bit of a mouthful.

This example is written with Hexo, Codeship and WebFaction in mind but should work with any static site generator, other CI services (e.g. CircleCI, Travis CI) and any server that allows authentication via key-based SSH.

It’s a little more fiddly than hosting static sites on Amazon S3, but putting a site behind Apache or Nginx can be useful if you need to use redirects or proper authentication.

Step 1

Create a new website in the WebFaction control panel, attaching a static application (name_of_webapp) and a domain.

Step 2

Create a new Codeship project (or use an existing one).

Add your build commands in the “Setup Commands” field under the “Test” configuration (if you’re using Hexo, it’s hexo generate). You can add any test commands you may have under “Configure Test Pipelines”, if you like.

Push a new commit to check that everything is building correctly and passing tests.

Once you have a green build, it’s worth opening an SSH debug session and making sure the generated files are present and as expected. Find the debug session tool on the right hand side of the appropriate build log page. Look in ~/clone/ for the folder your SSG generates (for Hexo, this is ~/clone/public/).

Step 3

Go to “Deployment” in the Codeship project settings and add a custom script for the branch you want to deploy. I use the following rsync command:

rsync -avz ~/clone/build_directory/


  1. name_of_webapp with the name you used for the static application in Step 1.
  2. username with your WebFaction username.
  3. build_directory with the directory your SSG writes to. As mentioned above, this is public for Hexo.

Step 4

Follow WebFaction’s Using SSH keys to add the Codeship project’s public key to your WebFaction account authorized_keys file.

Go back to Codeship and run the most recent build again to trigger a deploy. One the build has finished, you should be able to see the static site on the domain you set up in Step 1.

If this doesn’t work, here are some ideas for working out what might have gone wrong:

  1. Check the Codeship build log and look for issues
  2. Open another Codeship SSH debug session and check that the build step is generating the files.
  3. Check that the site files are under your WebFaction account in ~/webapps/name_of_webapp.

From Ghost to Hexo

I’ve moved this blog from Ghost to Hexo.

Why? I liked Ghost’s interface and it’s very straightforward compared with WordPress, but it has too many moving parts. I like editing posts with a real editor, or directly on GitHub for speed. Being able to hook everything up to a CI service and use pull requests makes life easier. So it’s static site generators all the way for me.

Jekyll is easily the most popular SSG (powering GitHub pages will do that) and it’s a fine tool, but managing Ruby is a pain. The same goes for Middleman: too Ruby. Hugo looks like it could be fun, but I’m not quite ready to leap into Go.

So, Hexo. It’s built with JavaScript and uses EJS and Swig for templating, so I can keep using the tooling I’ve been working on over the past couple of years. Getting started was fairly straightforward.

  • I installed Hexo locally. It was as straightforward as installing any other npm package.
  • My Ghost install was at 0.4.x, so I exported my posts using the not-so-secret ugly debug tools. It looks like this menu has been renamed “Labs” in more recent versions of Ghost.
  • I attempted to import my Ghost posts into Hexo with hexo-migrator-ghost. This failed with:

    $ hexo migrate ghost GhostData.json
    throw (e);
    TypeError: Cannot read property '0' of undefined
    at /Users/paul/Projects/anglepoised-notes/node_modules/hexo-migrator-ghost/index.js:27:21
    at fs.js:334:14
    at /Users/paul/Projects/anglepoised-notes/node_modules/hexo/node_modules/nunjucks/node_modules/chokidar/node_modules/readdirp/node_modules/graceful-fs/graceful-fs.js:104:5
    at /Users/paul/Projects/anglepoised-notes/node_modules/hexo/node_modules/hexo-fs/node_modules/chokidar/node_modules/readdirp/node_modules/graceful-fs/graceful-fs.js:104:5
    at /usr/local/lib/node_modules/hexo/node_modules/hexo-fs/node_modules/chokidar/node_modules/readdirp/node_modules/graceful-fs/graceful-fs.js:104:5
    at FSReqWrap.oncomplete (fs.js:95:15)

    Sigh. I couldn’t be bothered to debug this, so tried sucking the posts out of the existing Ghost feed with hexo-migrator-rss. This worked. Hurrah!

  • Mostly, anyway. I started the Hexo server with hexo server and noticed a few formatting issues. I have so few posts that repairing each by hand was the most straightforward way to fix this.
  • Hacking the URL from /year/month/post/ to /year/month/ didn’t work - no date-based archive pages. I should probably fix this at some point. Maybe hexo-generator-archive will do it.
  • Tags weren’t appearing on posts. I manually added them to the Front Matter in each post, and added tags: {{ tags }} to scaffolds/
  • The share tool at the bottom of each post pointed to This prompted me to sort out the config. This was trivial. It’s just YAML.
  • The default Hexo theme is a bit meh. I tried a couple from the theme directory, but they didn’t work for me. There are many more themes in this old list, but it’s not clear whether they’d work properly with the latest version or not. So, another thing to fix later.
  • I like favicons. It took me a while to work out that the favicon filename is set in the theme’s _config.yml and the file itself should be dropped into the /source directory.
  • The feed wasn’t being generated. I had to install hexo-generator-feed and update _config.yml to get this working.

    type: atom
    path: atom.xml
    limit: 20
  • I like using npm as a build tool so I made npm start run hexo server. Small beginnings.

I still have plenty of things I’d like to do (CI! Linting Markdown! Using PostCSS!) but I’m please that getting from zero to minimum viable blog was this straightforward.

It doesn’t matter that the tools are dumb

That’s what technology is. It’s the world of things, some impossibly stupid, some smarter than we are, we have assembled around ourselves to cover over our fundamental weaknesses as a species. The strength we have, the advantage this gives us, is our ability to stand apart from the things we’ve made: to use them and set them aside; to make them prosthetic extensions of ourselves and to let them go.

Why James Cameron’s Aliens is the best movie about technology