Development environment — itch v25 postmortem, part 2
Sep 14, 2018
5 minute read

One of my goals with the v25 release was to make it much easier to develop, test, and distribute the app.

Base tools

I typically develop the itch app under Windows 10 or a Debian-based Linux.

The set-up is mostly the same for both OSes. You’ve got your standard unix tools, tmus for panes, git, and that’s about it. I prefer zsh, but bash (with a few aliases stolen from prezto) will do when I’m using msys2.

Starting itch in development is as simple as cloning the repo, running npm i (install), and running npm start.

Startup in the development environment is handled by a node.js script that uses the webpack 4 API. In particular it:

  • Bundles javascript for the main process
    • and writes it to disk
  • Bundles javascript for the renderer process
    • and serves it over HTTP
    • …watching for changes
    • …and serving bundle updates via WebSocket
  • Starts electron, pointing it to the freshly-compiled code.

It uses HappyPack for parallel compilation and the hard-source webpack plug-in to cache as much as possible. That means npm start is relatively quick. There’s still a lot of disk reads happening and processe spawned (so it’s much faster on Linux), but it doesn’t need to compile anything that hasn’t changed.

In development, itch starts up as kitch, the name of the beta. The application log can be opened directly in the app, even though I usually just keep an eye on the terminal window.

Pressing Ctrl+Shift+C opens up the Chrome developer tools for the current window. Using that keyboard shortcut again focuses them if they’re already open (something I had to explicitly add last minute! so many seconds wasted looking for the devtools).

If you have the React devtools installed in Chrome, they get loaded up and are available here too:

I use the Chrome developer tools mostly to figure out margin, padding, or flexbox attributes, but also to execute JavaScript directly:

Of course, if I just wanted to check out the app’s state, I would use Ctrl+Shift+click on the app’s logo, and then I’d access a fully searchable state tree:

The whole frontend (all React components) have hot-module-reloading enabled, so if I change something from vscode, it changes in the app.

I’m using VSCode with a few plug-ins and its Vim mode enabled. It already comes with excellent TypeScript support out-of-the box (with fast reference searching, refactoring, etc.), but one of my favorites is enabling format-on-save, with prettier.

VSCode also comes with a built-in debugger (that can be used for either the main or renderer process of Electron), but I tend to use Chrome’s developer tools for that.

The butler daemon

Another big use for the Chrome developer tools is to inspect requests the app makes to butlerd. For example, when it first starts, it lists remembered profiles:

In this case, the <LoginScreen/> is making that request. As far as the browser runtime is concerned, we’re calling an asynchronous method.

As far as TypeScript is concerned, it’s well-typed:

..but in fact, it’s making an XHR request thanks to node-butlerd. butler receives the request, and executes the request handler:

…then serializes the response to JSON and sends it back as the HTTP response.

Every butlerd endpoint is defined as a series of Go types:

Then, a custom-built tool, generous, uses part of Go’s compiler toolchain to parse that file, and generates four things.

First, it generates Go boilerplate code that helps work around the lack of generics. It makes it easier to implement request handlers, call them in testing, etc.

Second, it generates a human-friendly documentation, from both the types and the comments:

Some of these types actually come from go-itchio, since butler is not the only program that consumes the itch.io API. Regardless, generous parses them all the same.

Thirdly, it generates a JSON description of all endpoints:

This is used by cutter, a little CLI client, to provide tab-completion and show inline help:

Finally, it generates TypeScript typings for all endpoints.

node-butlerd provides base types like Request, Notification, and generous generates a file that imports those types and creates more specific subtypes, for each possible request.

Typings for the endpoints are actually stored directly in the itch repository, so that they can be updated without having to release a new node-butlerd version.

Having every butlerd method fully typed is a huge quality of life feature. It means TypeScript verifies usage (to some degree), and provides auto-completion and inline documentation:

I’ve used cutter heavily during butlerd development, so I built some other development-friendly features into it, for example, being able to rebuild butler and re-establish a connection to a fresh instance with a single command. (rb, for “rebuild”).

Miscellaneous

Here’s a few tools I forgot about, but couldn’t do my work without.

SQLite Studio is a very good graphical interface for SQLite. I use it often to draft queries or just look at some data. Here I’m using it to delete a bunch of data and see if itch can recover it by scanning the disk:

I’m obviously a huge GitHub user. My commit hygiene1 still varies, but I successfully used a 4-column GitHub project setup, and ended up filing and closing almost 600 tickets:

I haven’t bought a third MacBookPro yet, and the other two are dead, so I use NoMachine to access a mac we rent at MacStadium:

Enough with development!

In the next instalment, we’ll take a look at some testing infrastructure. I hope you’re enjoying these!


  1. Make small commits with descriptive messages, that only change one thing at a time. Never break the build to allow bisecting, etc. [return]