Building GitHub Pins
One of the more interesting projects I’ve worked on recently is GitHub Pins, a prototype feature I worked on with my colleagues Jon Hoyt and Harrison Tuow at GitHub.
The premise is simple: Let’s have a way to bundle together collections of any kind of GitHub resource—a commit message, a pull request comment, a repo, a project board, a help doc…a link to that obscure settings page you always have to Google for…you get the idea. Basically, anything GitHub exposes via a URI.
The motivation came from observing my work patterns and those of my teammates. Over the course of a project, the number of development artifacts to which I’d need ready access—mainly comments and discussion threads scattered throughout various issues and pull requests—would proliferate, and I’d end up with a ton of pinned and open tabs cluttering my browser.
This made re-gaining context a chore. My workday would typically start with opening up Chrome and seeing something like this:
Not terrible…but that’s at the start of the workday. After a few hours, finding such-and-such issue or PR amongst all the open tabs would become an annoying source of friction for me.
Asking around, I found that my experience wasn’t unique: Other adaptations included creating bookmark folders for each project, using a new browser window for each project / set of open tabs, or just using Google as the index to GitHub, so to speak. (That last one seemed somewhat damning of GitHub’s navigation UI, which broke my heart a little. More on that later.) None seemed satisfactory from a UX perspective.
The remedy I came up with, cast as a high-level user story and preliminary feature spec:
Feature: GitHub Pins As a GitHub user In order to keep my workspace uncluttered And in order to find development artifacts seamlessly I want to store links to frequently-used GitHub resources on GitHub itself Scenario: Given I have saved links to a repo, a PR, and an issue comment When I visit the root url Then I should see links to that repo, PR, and issue comment And I should see those styled with the appropriate octicons
On the back-end, the implementation rests on a polymorphic many-to-many
association between the
users table and a
pinnable_item, a stand-in for any
model to which we add a polymorphic
has_many call, for example:
# app/models/repository.rb class Repository < ApplicationRecord has_many :pins, as: :pinnable_item end
Because not all pins have pinnable items backed by Rails models, there’s also a
path column on the
pins table, so that if a pin’s creation is initiated from
a form with no
pinnable_item_type, we instead persist
the resource’s path and, when rendering pin models in the view layer, display a
generic “link” octicon.
When I first shared this idea with Jon and Harrison their enthusiasm was palpable and they breathed life into it in ways that surpassed my own vision for the feature. Jon immediately leapt on a use case from his own experience: a certain frequently-used settings panel he’d often find himself digging for. That provided the impetus for also handling resources not backed by a database record. Another brilliant idea was collecting pins in (eventually shareable, we hoped) collections, to facilitate context-sharing and onboarding: instead of dropping five URLs into slack, drop one. Or just update a shared board.
The stroke of genius of the Pinterest-like interface was all Harrison’s. Instead of cramming pins into a “widget” like those currently on the homepage, we could let them breathe a bit and allow the user to reorder them as desired. The end result was not only aesthetically graceful, but leveraged a well-understood UX idiom to communicate how to use this feature to maximum effect:
Finally, here’s the finished v1 in action:
Although it never shipped on
master, I had high hopes for GitHub Pins.
Possibly my favorite bit of UI on GitHub is the fuzzy-search feature when viewing a repository (hit “T”, and a drop-down appears letting you fuzzy-search for files in the repo).
It would have been great to build similar functionality for pins—something akin to an application launcher, Atom’s command palette, or Emacs’s Smex. That would go a long way toward improving navigation on the site—instead of using Google as GitHub’s index, hit, say, Ctrl-T, type the first few keystrokes of “Linguist”, and boom—there’s a list of relevant resources, with your pins stacked at the top.