Earlier this year, we rewrote the architecture of this blog. It is
composed of a Rails application (the blog engine) and a separate repository of
Markdown files. Whenever a new commit is made to the master
branch of the
markdown repo, the blog engine is notified via a webhook and automatically
imports the changes and publishes them.
As an author all you have to do is write a Markdown document and merge to
master
after getting it reviewed. You don’t need to know about the blog
engine, Rails, or webhooks.
In theory.
Previews
Authors like to preview their content before shipping it. Markdown previewers, although a step in the right direction, created output that was very different from what a post would look like on production. Not only did they not match the style of our blog, but they also lacked all the other UI elements that would normally be present such as the header, tags, and authors.
The blog engine has a local preview mode that reads posts from the local file system instead of the database. Problem solved!
In solving one problem however, we’d created another. Now authors needed to install the blog engine locally, run a server, and point it to their local copy of the markdown repository. In addition, they needed to update the engine as changes were made to it as well as keep up with versions of Ruby and Rails.
Addressing the problem
We received a lot of feedback that the process of writing a blog post had become convoluted and confusing. First-time authors were frustrated with all the tools they had to set up before they could even start writing. Something needed to change.
The new approach needed to solve the following:
- Give authors the ability to preview their work in a way that would look identical to production
- Completely remove the need for authors to know about the blog engine
- Not force authors to manage Ruby and Rails versions
Shell scripts to the rescue
We eventually decided to add a shell script ,bin/server
, to the markdown repo
that would boot a “preview server”. The process for authoring a post is now:
- Write Markdown document
- Run
bin/server
and preview post in browser - Open pull request
All of the complexity that was previously so frustrating is now hidden behind
the bin/server
command. This script tries to clone or update the latest
version of the blog engine into a temporary directory. It configures the engine
to run in local mode and points it to the local markdown repo. It will also
automatically install the correct Ruby version. Finally, it boots up a server.
Adding a small shell script vastly improved the experience of authoring a blog post. This was particularly true for our designers. They don’t spend their entire day in the shell and thus have a lower tolerance for arcane processes that require running a lot of different shell commands.
As someone who was not only an author, but also worked on developing the blog
engine, I had gotten used to all the hoops I needed to jump through. Once we
introduced bin/server
, I was surprised at how much pain I had previously
considered acceptable.
Cleaning things up
Iterating on the script idea, we found that authors thought the output
bin/server
command was both overwhelming and a little confusing. Most of it is
not necessary unless you are debugging. It was time for a second round of UX. We
redirected most of the output into a server.log
file where it was out of the
way yet still available if we needed to debug. We added better error messaging
and colorized important lines in the output to emphasize function.
Bonus points
Authors sometimes encounter small bugs in the blog engine. Once we push fixes to
the repo, all authors need to do is re-run bin/server
, and they will be
running their preview server on the latest code automatically. Although we
didn’t set out to build this functionality, it turned out to be a very nice side
effect of our efforts to improve user experience.
Lessons learned
User experience is important, even for developer tools. Just because you are comfortable with the terminal doesn’t mean that it’s not worth improving a complex workflow.
Just as with user-facing products, get feedback from those that use your dev tools and iterate on improving the interface and experience.
Distill your workflow to its essential components and hide unimportant details behind abstractions. Use color and spacing to make the output of your scripts intelligible and hide information that isn’t useful.
Source code
For those interested, you can view the source for the bin/server
script in
this gist.