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:

Tabs tabs tabs

Tabs tabs tabs

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

    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

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_id and 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:

The pins index

The pins index.
Inside a pins collection.

Inside a pins collection.
Moving pins around

Moving pins around


Finally, here’s the finished v1 in action:

Consolidating tabs into a shareable pin collection

Consolidating tabs into a shareable pin collection


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.