Powered by Fusion

Shipping the new GitHub Issues

We started work on the new GitHub Issues over nine months ago. It was a bit of a crazy ride, but I’m honestly stoked about what we shipped. For the quick low down on what shipped, read the GitHub blog post.

Given the length and scope of the project, I wanted to share more than that blog post and tell the story of how we went from a single pull request to the shipped feature you see today.

Buckle up.

Table of contents

Instead of splitting the article, I figured I’d write until I couldn’t and just give y’all a helpful table of contents.


Perhaps the most important question is why would we even work on Issues? And what exactly would we do with it? How did we know that it needed the love?

Use it to improve it

We spend most of our time on issues at GitHub. Internally, we use the hell out of Issues for everything. Have a problem with the office? Open an issue. They’re a written record, cheap and fast to create, and searchable. Between our extensive usage internally and the number of folks here contributing to open source projects, we’re some of the most prolific issues users.

Bottom line? There was no one thing that motivated us to do it. We just started to notice some things that could be better, like:

  • It was starting to feel dated compared to other aspects of the site and enough folks spoke up about it.
  • The interface was a bit cluttered with nav and filters on the top, right, and left sides.
  • Searching for issues was an entirely different experience. We didn’t have a dedicated search for issues, so when you searched for a specific one, you left your repo’s issues list and landed on a search results page. From there you couldn’t triage any aspect of the issue until clicking into it.
  • We were missing a bunch of information on the issues and pull request lists—task list progress, milestone name, build status, etc.
  • At least two of us wanted to work on it, and we both were excited by the possible outcomes the more we talked about it.

Once we had that kind of feedback shared (you know, if you see something say something), and folks agreed that those were worthy problems to solve, we got to work writing code.

For what it’s worth, this is just about how all product or redesign work goes on the GitHub.com side. Find a problem, propose a solution (usually with code), get feedback, and find a way to ship it. We’re looking into how we can improve this and apply a process or checklist to all great ships, but that’ll take some time.


We didn’t spend much time looking at analytics or metrics for Issues before diving in, but we have historical data we can compare against. Throughout the project we tried to optimize our database reads and ensure we didn’t have extra HTML and CSS lying around, but that’s about as far as we got for the front-end performance stuff.


Before I get to the good parts, first let me explain a few things about how all this went down logistically as it’s important to have a bit of context for this given our usual shipping speed.

Nine months!?

So, first, why nine months?

  • We had two large related projects going on at the same time: the issues redesign (internally and hereby called Issues 3) and our conversations redesign.
  • The conversations redesign took our attention away from Issues 3 after a few weeks. Ultimately it derailed us for around three months while we iterated, shipped, and cleaned up after ourselves.
  • We had a bit of trouble keeping the two projects separate. We ended up blending some ideas and that also set us back.
  • We improved a ton of our infrastructure around search and issues performance.
  • We spent a lot of time trying things out for a week or so between bigger iterations. Our goal was workflow improvements, so we need to work with these ideas more so than other ships.

It was a challenge for all of us—me in particular—at balancing two separate-but-related efforts. Crossing the streams ships meant adding complexity, spinning our wheels, and losing sight of the specific end goal for each ship. I think we did an alright job of realizing that quickly enough and ended up getting a ton of work done.


The Issues 3 core team was essentially three people: two developers and one designer/frontender (me). The extended team included our Ops and database folks, search engineers, and people from support and docs teams. Plus, dozens of others in the company who provided feedback via issues and pull requests throughout.

Working together

We found out really early on that all of us on the core team worked pretty damn well together. We moved fast, broke things, opened tons of pull requests and issues, called each other out on bullshit, propped each other for amazing ideas. Most of it happened fluidly and off the cuff. There was hardly anything formal about it until we were near ship time.

Here are two examples of how most of our work was done.

Issues were opened with specific feedback by one of us (or others across the company), labels added, milestone set, and someone assigned. When we had fixes to deploy, we opened pull requests.

We’d try to be as detailed as possible. We included screenshots, /cc-ed the right folks (e.g., the @github/issues team), and then quickly shipped it. Given the early work on Issues 3 was only team shipped, we could afford to screw things up every now and then because only we would be affected.

There was still a chance of screwing up other things mind you, and I may have done just that a couple times, but we were pretty well shielded.

In issues and pull requests, we’d use task lists whenever possible. Similar to full fledges issues, we’d try our best to be super clear and assignee folks or ask for help when we needed it.

Those issues task lists were especially useful when we got closer to shipping and could use them to do production readiness reviews, check in with the docs team on how their updated screenshots were going, and review last minute tweaks or bug fixes.

Put another way, we used GitHub Issues to build GitHub’s new Issues, and it was pretty damn awesome.

Opening a pull request

Okay, now, back to the product work.

A bunch of us had been talking about updating Issues for a long time, but it didn’t take off until Holman opened the first pull request. (That’s often the case—some ideas just stall out without some code to kick them off.)

The first Issues 3 pull request was opened back in October of last year, and while the aesthetics and layout details changed a lot over time, the core idea never did. This would make search the interface.

The idea itself didn’t feel all that radical, but it did heavily influence the architectures and interface. Under the hood, we leaned into Elastic Search and MySQL to build out the functional tidbits. Today, Elastic Search powers all the custom search queries while MySQL handles the general issue and pull request listing and more.

Interface wise, it’s pretty clear that search was the focus early on. That search bar was huge! Everything you did updated the search bar, and heck some things were (and still are) just easier when you type in the search input. I was honestly hesitant about this, but the team’s excitement kept us moving.

Determining features

That first pull request had it’s own feature set: more search, triage mode (bulk actions), and faster access to issues. Along with that first iteration though came a bunch of spontaneous ideas from within our team as work progressed.

Quite a few of the features we shipped with actually came organically out of that.

  • Search is obviously the huge feature focus in Issues 3, but the specifics were worked out as we went. We defined the search syntax, added negation searches (like no:label), and more state queries (like is:merged) as we went along.
  • We found ourselves doing the same simple searches over and over again, so we restored the old quick filters (like Your issues) and added a few more.
  • Our audit log—the history of changes to titles, assignees, labels, and milestones—went from offhand comment to part of Issues 3 in just a couple weeks.
  • Notifications on assignee changes went the same way. A few of us were talking about notifications one afternoon and we realized this wasn’t a thing yet. So, we coded it up and made if part of Issues 3.

We had a quite a few things in mind from the start, but just as many important features came naturally out of actively using the thing we were building. While that added extended the time we spent on the project, it was absolutely worth it.

Separately, one thing that’s come up a lot in the last several months has been project management on GitHub. The term project management is rather vague. There’s a multitude of ways in which this could manifest in GitHub, all of them independent of improving our existing issues and search infrastructure and interface. As such, it wasn’t part of this project.

I’m specifically avoiding talking too much about what we didn’t ship as there’s still a good chance we’ll ship those things. I don’t know when, and I don’t know how, but there’s still so much we can do with Issues—a fact I’m sure no one will disagree with.


The early months of our work on Issues 3 (after those new conversations shipped) was mostly spent churning out iterations on the interface. While others focused on the underlying code, I fiddled around with the layout, aesthetics, and more. Here are a bunch of those iterations and a few brief notes regarding each.

Earliest iterations

As mentioned earlier, this was the opening screenshot of the issues index page, the work of one engineer just going to town on what a vision for Issues could be. Turns out he was pretty spot on as well.

The design is rather inbox-y with the huge search, buttons for filtering and triaging, and the single line issues list. The reason for that was to add and streamline information to keep it in a single row for more content per page. One line per issue was a bit of a crazy goal and we’d struggle to keep to that as we iterated more.

This screenshot is a bit of a mess as you can tell. It was from one of those interstitial states where the conversations redesign and Issues 3 were becoming confusingly intertwined. The omnipresent search at the top was one (bad) idea we tried to carry over from the issues index to individual issues.

We also tried to have no sidebar on issues with this—you can see the milestone, assignee, and labels at the top of the page. Things got messy, but we were fast and flexible enough to quickly try out and discard ideas.

Once that initial design was merged—it was team shipped, which meant only a few GitHubbers had access to it—I started tweaking the design to explore slightly different directions. Briefly, here’s the what and why:

  • I minimized the search field because I still didn’t think search would or could be the primary interface for people of all ranges to interact with first.
  • I condensed the search and filter buttons into one row so you didn’t lose as much vertical real estate.
  • I tweaked the display of content in the issues list by collapsing labels into dots (revealing the label name on hover via tooltip), giving more weight and contrast to issue titles, and adding more content in a slightly more tabular design.

One of my favorite aspects of this was the arrow to avatar for assignees. To me it read super naturally—issue titled such and such assigned to username. Later it’d cause problems for aligning and wrapping longer content.

The design of that issues list page also mapped to the individual issue again. Things were getting even more mixed up between Issues 3 and the conversation redesign as I streamlined the gray bar and the assignee, milestone, and labels lists into it. Notifications also got moved up from the bottom of the page to a single button on the top right.

The goal here was to present all your actions above the rest of the page content. This way, hierarchically, it reinforced the idea that you were taking action on this page—this issue.

There are some more failed ideas in here from an earlier iteration of the conversations redesign. The state indicator—the thing tells you it’s an issue or pull request, and if it’s open, closed, or merged—was like a big avatar. The opening comment was (literally) unboxed and enlarged to function as a sort of blog post style introduction to the issue or pull request. This never really ended up working out as it brought with it a few annoying differences across how we layout comments and render their Markdown content.


For a long while most of my changes felt superficial. I played with button styles, orientation of search and filters, and different representations of content within the issues list.

I removed the light gray background to prevent more horizontal stripping of content, something GitHub and tons of other sites seem to struggle with. Other super subtle changes include lightening the comment bubble and count for issues without comments.

More visual changes as I try out lighter button styles to make the page feel less full of administrative cruft. It wouldn’t work out that well for buttons originally, but those styles later resurfaced in our subnav.

I spent far too much time flipping between icon-only buttons and icon-text buttons. At this point I also started to solidify on some of the more basic aspects of the issues list that I stupidly tried out earlier on. For example, I started expanding the labels again to their natural textual state. I also restored the stateful color—green or red for open or closed—to the issue/pull request icons on the left.

Searching vs. filtering

While I struggled with it repeatedly, there was a moment when I suggested we abandon the new search field entirely.

It was starting to annoy me that I had up to three ways to get to things:

  1. Clicking the filter buttons
  2. Searching by hand
  3. Hacking the address bar and using URLs only

It felt odd that we had so many avenues to get to the same content. Eventually though, I’d come to peace with this and realize it was an advantage. Some folks love using buttons for everything, some work faster typing and using keyboard shortcuts, and some love their address bar more than life itself.

Put another way, the more access points, the more we could appeal to different workflows across teams and organizations.


Throughout our work on issues and conversations, I frequently got care-mad about the intersection of our repository navigation, page headers, section subnav, and our issues filters. I also got fed up with the single-line issues—it just wasn’t working.

So I started screwing around with more subnav-search-filters layouts and the placement of content within the issues list. The subnav moved around from the top right of the page header to the top left of the issues list and more. I think we flipped around and tried out even more ideas, but mostly these were our two “best” options.

The table-header style approach to our filters here was one of my favorite aspects as well. It felt simple, elegant, and functional and came without all the added weight that a series of buttons brings.

We realized for awhile that because we had moved the subnav—previously tabs in the old issues UI—to the page header, we suddenly had more room again. That meant making the search field ginormous again.

But something still didn’t feel right in that layout. The hierarchy felt lost again and it was rather difficult to find relationships between content and quickly find things.

At this point I panicked for nearly an entire day. I gave up everything about the new layout and tried a few ideas to see if a tabbed interface and side column would make more sense again. I don’t know if it’s just because what I tried was absolute shit or if the idea just didn’t make sense, but it felt wrong.

Seeing that it felt wrong again to try the side column and tabs, I starting feeling a lot better about our new direction.

Additional views

While all this work was being poured into the main issues list, we had plenty of other iterations on labels and milestones. Labels in particular are fun to compare before and after:

The original pass was kind of fun and quirky, but not the most practical.

We toned it down and shipped a super basic one-page list of your labels. We wanted to add more sorting and metrics, but time just didn’t allow it. Maybe next time around.

We spent a decent amount of time thinking about how to educate folks about available search queries. Two earlier options include a popover when focusing on search and a set of links at the bottom of the issues list.

Compared to a set of callouts below the content:

We ended up shipping a much more streamlined version of those at the bottom of the issues list. It was easier to work with, easy to ignore by more experienced users, and a fun surprise for those new to the feature.

Settling down

So, I went backwards again to the table header, narrower search button, and a closer subnav for the issues, labels, and milestones links.

Instead of columns like some earlier iterations though, I switched to plain text “buttons” all right aligned above the issues list. Given that they weren’t typical button styles (gradients, box-shadows, etc), it felt lightweight and approachable.

There was a bit more churn around the subnav and issues list:

  • Added a border around the entire list of issues and the table header
  • Set the filters (open/closed, labels, etc) against a light gray background for contrast between chrome and content
  • Tweaked the subnav styles, trying out gray text links, nav pills, and then ultimately a segmented controller style nav
  • Search styles to clarify the proximity of the quick filters dropdown menu and new issue button

Even with those changes, this was basically the last big iteration we went through before shipping.

Validating our ideas

The thing about working on a single project for so long was how do we know when to stop? I struggled with this a bit. When you’re working for so long on something, you get tunnel vision and don’t want it to end. You keep telling yourself you’ve got time for one more tiny feature or one more UI change.

One day I noticed something though. Whenever I wanted to churn through some Bootstrap issues, I was disabling staff mode and reverting to the old issues interface. As it turns out, I wasn’t able to get any real work done with the current design.

So, that became the test for me. I’d know we were on to something awesome if I could binge close dozens of issues without using the old interface.

For some reason we never really got to do dedicated user research studies on Issues 3. We had plenty of time, but it never solidified. We did have tangential feedback from related studies, our sales team, ourselves, and our peers who we teased with early iterations.

Shipping it

The task of actually shipping Issues 3—after all the design and development was done—is mostly a familiar process to us. There were a few unique aspects for a ship of this size, but overall it went something like this:

  • We finished off all our product work and shifted gears to the blog post, small bug fixes, etc.
  • Given we had rewritten and improved much of our infrastructure, we had some basic production readiness reviews with our Ops folks (far too late in the process mind you, but it was better late than never).
  • We dark-shipped it a couple times to more accurately simulate the changes in performance. (Dark-shipping refers to silently calling a new feature’s functionality in production alongside the existing functionality. This way, you get real metrics on how folks use the service for both versions.)
  • When we were ready for it to go into “genpop”, we flipped the feature flag and redeployed to our servers.
  • After watching the graphs in Chat for 10 minutes or so, we decided it was ready to go and merged into master. Boom, it was shipped!
  • Once we shipped the code, we shipped the blog post and all our documentation updates that our support team had made. Without those last two, the whole ship is a bust as support requests become a shit show rather than what I like to call a coordinated chaos.

That’s greatly simplifying it, but I’m not trying to provide all the technical details. That’s way too much for this post. Suffice to say we had an amazing set of dedicated individuals and teams to help us ensure a quality ship.

Our Support team is always invaluable when it comes to shipping (big) features. They triage incoming feedback, bug reports, and the like so we can more efficiently react and quickly ship follow-up tweaks. I can’t stress enough the importance of that workflow to the success of this project.

Wrapping up

Issues 3 wasn’t without its problems, but we worked our asses off on it for months and the launch has been overwhelmingly successful. I’m sad I don’t have more metrics and user feedback to share, but we simply didn’t collect enough of it throughout the process. Next time, we’ll do even better.

And on that note, here’s to the next :ship:!

Continue reading...

GitHub's CSS

I’m always interested in the development details of other products, particularly their styleguides and approach to CSS. Given my penchant for the otherwise inane CSS details, I decided to write a bit about GitHub’s CSS.


Given the length, here’s a helpful table of contents.

Quick facts

A survey of our current state of CSS shows:

  • The preprocessor of choice is SCSS.
  • We have well over 100 individual source stylesheets that we compile before serving it up in production.
  • That compiled CSS is served via two separate stylesheets to avoid the IE<10 selector limit.
  • Those two stylesheets weigh in at around 90kb total.
  • There’s no particular “CSS architecture” in place.
  • Pixels are the unit of choice, although we do have some ems lying around.
  • Added 7/24/14: We use Normalize.css and a mix of our own reset styles.


As mentioned above, we use SCSS. This was a choice made much before my time and I’m a-okay with it (despite Bootstrap currently being written in LESS). Our SCSS is compiled by the Rails asset pipeline with some help from Sprockets (for the time being) for including the files. Read about that a bit farther down.

What about LESS, or Stylus, or …? I don’t think LESS was ever a choice for GitHub, but I can’t really speak to that. We probably wouldn’t switch at this point either as there is no clear benefit.

Why a preprocessor? Our internal framework includes a relatively small set of variables (like font stacks and brand colors) and mixins (mostly for vendor prefixed properties) that make writing code faster and easier.

We don’t currently use Autoprefixer, but we really should as it would basically negate all our existing mixins. Hopefully we’ll implement it soon.

We also don’t currently use source maps, but that’ll be changing soon. (If you don’t know, source maps allow you to see in the Inspector what source SCSS file a particular set of styles are coming from rather than a compiled and minified stylesheet. They’re awesome.)

Added 7/24/14: Other than that, our use of the tools SCSS provides is quite limited. We use color variables, mixins, color functions, math functions, and nesting. We don’t need to iterate over classes, set global options, or anything else really. I enjoy the simplicity this affords.


Common CSS architectures include BEM and OOCSS. We lean towards OOCSS, but we have no holistic approach. We do tend to write all our new stuff with a nebulous but basic approach:

  • Aim for classes over everything else in selectors
  • Avoid unnecessary nesting
  • Use (single) dashes in class names
  • Keep things as short as possible without adding confusion

I’ll write more about my preferred CSS architecture in another post. For now, the above sums up GitHub’s approach, which while not perfect, serves its purpose well enough.


We didn’t start linting our SCSS until several weeks ago. We had common enough conventions, but everyone’s style and formatting was somewhat unique. Today, every CI build includes basic SCSS linting and will fail if:

  • You have a class in your CSS but not anywhere in your app/views/ templates.
  • You are using the same selector multiple times (as they should almost always be combined).
  • The general formatting rules (nesting limits, line breaks between rulesets, lack of space after :s, etc) are broken.

All in all, these few rules keep our stuff decently tidy. It doesn’t account for discrepancies in commenting styles or general architecture, but that’s the stuff teams need to address themselves with real documentation. It’s something everyone here is open to improving and iterating on.

Two bundles

GitHub.com has two CSS bundles, github and github2. The split was added years ago to solve the problem of Internet Explorer’s 4,095 selectors per file limit. This applies to IE9 and down, and since GitHub requires a minimum of IE9, our split bundle approach must stay.

This is because, as of today, GitHub has around 7,000 selectors across those two files. How’s that compare to other sites?

  • Bootstrap v3.2.0 has just under 1,900 selectors
  • Twitter has just under 8,900 selectors
  • NY Times has just under 2,100 selectors
  • SoundCloud has under 1,100 selectors (Edit: Previously I reported this at 7,400, which is the old SoundCloud)

These numbers were gathered using cssstats.com. It’s an awesome little tool that looks at your CSS in ways most folks, including myself, usually don’t. We also have graphs for this internally at GitHub and usually use those for our own purposes.

Included via Sprockets

GitHub’s CSS, and JavaScript, is bundled via Sprockets and require. We maintain our two CSS bundles with separate subdirectories within the app/assets/stylesheets directory. Here’s how that looks:

 = require primer/basecoat/normalize
 = require primer/basecoat/base
 = require primer/basecoat/forms
 = require primer/basecoat/type
 = require primer/basecoat/utility
 = require_directory ./shared
 = require_directory ./_plugins
 = require_directory ./graphs
 = require primer-user-content/components/markdown
 = require primer-user-content/components/syntax-pygments
 = require primer/components/buttons
 = require primer/components/navigation
 = require primer/components/behavior
 = require primer/components/alerts
 = require primer/components/tooltips
 = require primer/components/counter
 = require primer-select-menu
 = require octicons

 = require_directory .

We include our dependencies—Primer is our internal framework—and then load the entire directory’s SCSS files in whatever order Sprockets decides to include them (I believe it’s alphabetical). The ease in which we can bundle our stylesheets—by simply writing require_directory .—is awesome, but it also kind of sucks.

The order in which styles get applied matters. It really shouldn’t, but in every design system there are rules and a basic hierarchy of styling. With the Sprockets approach, we sometimes run into specificity problems. This happens because new files can be added to either bundle at any time. Depending on their file name, they appear in different spots in the compiled CSS.

Additionally, using Sprockets means that your SCSS files don’t have immediate and automatic access to your global variables and mixins. That means you have to @import them explicitly at the top of any file that references a variable or mixin.

Given the repetition and occasional specificity headache, we have a pull request open to switch to explicit @imports. The added benefit is clearer insight into our CSS and easier willy-nilly experimentation with our aforementioned bundles. The downside is having to maintain that list, but I like to think of this as an added control to the overall system.


Added 7/24/14: Bundle sizes and selector count graphs.

Internally we use tons of graphs to monitor how the site and API are doing. We also track a few interesting frontend stats. For example, here’s the size of our two CSS bundles for the last three months:

GitHub bundle sizes

Similarly, here’s the number of selectors over the last month on our blob (or file) pages. Clearly we still have some work to do there to get those element tag selectors down.

GitHub selector count

Because we regularly deploy updated CSS, and we deploy dozens of times each day, we’re constantly busting the caches on our decently large CSS files. We haven’t done much in the way of optimizing these file sizes or limiting the cache busting, but we are starting to look into that more closely. It’d be awesome to have a core bundle that hopefully changes very infrequently and secondary bundle that can be more volatile.

Speaking of which, at Twitter we had (I’m unsure if they still have this) two bundles, core and more. core was all the styles needed to keep the time to first tweet number as low as possible. Everything else was in more. Given GitHub’s love of all things fast—here, it’s not shipped until it’s fast—it’s something we plan on looking into. Currently our bundle split is arbitrary.

Generally, selector performance isn’t something we concern ourselves with. We’re aware of bad practices—over-nesting, IDs, elements, etc—but we don’t try to over optimize. The one exception has been diff pages. Due to the extensive markup required in rendering a diff, we avoid attribute selectors like [class^="octicon"]. When used too often, those attribute selectors can (and have) crashed browsers.

For the curious, Jon Rohan, a fellow GitHub design-gineer, has a great talk about GitHub’s CSS performance that covers these problems.


GitHub styleguide

Speaking of which, we do an okay job of this, but we’re working on making improvements. We have a publicly accessible CSS styleguide and all our general rules for writing CSS live there, as well as examples of most components. It’s built on KSS, a styleguide generator of sorts, and lives right in the github/github code base.

It’s not perfect, but it helps folks find and use things. It’s also a great way to show new folks how we do things to get them up to speed faster (like me when I joined nearly two years ago).



I alluded to it earlier, but for folks who don’t know, Primer is our internal framework for common styles and components across our public and internal apps. It includes:

  • Normalize
  • Global styles for box-sizing, typography, links, etc
  • Navigation
  • Forms
  • Grid system
  • Markdown styles
  • Custom select menu

We use it on GitHub.com, Gist, and several internal apps. As a rule of thumb, if it can or should be used in another app, we consider putting it in Primer.

Most of Primer’s components are documented in our styleguide (e.g., navigation, tooltips, etc). However, we’ve recently been going to town on updating and improving Primer, so lots of things are in flux there. We’ll be updating that soon to include all the things.

And for those about to ask, I’d love to open source parts of Primer, but there’s not much happening on that front in the near future. I’m hopeful though.


We have our fair share of legacy code at GitHub, and that includes our CSS. Unlike a public open source project with strict versioning rules, we burn shit down regularly if it suites us. Finding things to remove tends to happen one of two ways:

  • Manually finding things that look alike but actually have different HTML and CSS, then combining them.
  • Running a script that greps for a class in our CSS to see if it exists in our views. (We’ve recently made this part of our CI tests, so we constantly see it now.)

The actual process of refactoring CSS is probably not unique to GitHub. We find shit to remove, burn it down, open a PR, ping the CSS team, and ship it as fast as we can. As to who removes code, anyone can do it. We have tons of great folks adding to GitHub, but we also have just as many nerds looking at what we can remove.

Continue reading...

GitHub.com flow

The term GitHub flow refers to how one can develop software with GitHub. It’s a process that minimizes friction, enables asynchronous communication (and development), and is decently flexible. For an overview, read Understanding the GitHub Flow on GitHub Guides.

Applying the GitHub flow to development of GitHub.com The Website™ builds on that, and tends to go something like this.

1. Find something to work on

Issues on the github/github repository are the easiest way to find things to do. Anyone can open them, and anyone can comment on them. User and team at mentions are available for pinging folks with bugs, feedback, or questions.

It’s worth mentioning though that we sometimes jump right into code from a meatspace discussion or from a tweet. Twitter is the best way to find out if we have bugs or performance problems in real-time while deploying code.

Bottom line? Get to writing code as soon as possible.

2. Branching

At GitHub, almost every new contribution happens in a branch. What’s in master should always be stable, passing tests, and ready to deploy in an instant. When I figure out what I’m working on, I cut a branch from master and get to work.

My branch naming scheme is sometimes serious and relevant, and usually not useful in the slightest. sidebar_hit_areas and today_we_celebrate_our_independence_day are both branch names that I’ve recently worked on. Both are long gone though.

Great branches really should include accurate names, but most of the time it doesn’t matter because they’re so short lived. Plus, snagging the name of a branch is as easy as copy-pasting from the top of a pull request.

Bottom line? Just cut a branch and write some code.

Not every change happens in a branch. Super small changes can be made right to master should the occasion, or emergency, call for it.

3. Pull requests

Branches are ephemeral. They exist for the sole purpose of creating a pull request. Pull requests are more important than branches for a number of reasons:

  • Suggested changes are (justifiably so) more likely to be shipped if there’s an available pull request for it.
  • Branches get deleted, and thus code can be lost. Pull requests are never deleted, only closed or merged.
  • Pull requests, like issues, are search-able, label-able, milestone-able, and mention-able. Branches? Not so much.
  • Pull requests can be discussed in the open and linked to.

Pull requests should be created as soon as possible. You should push your code and open a pull request when:

  • You have changes that are completely finished and just need review before merging.
  • You have a bunch of things to do and need to use GitHub task lists to outline what’s left.
  • You have questions and have no idea how to finish a part of your intended changes without pinging coworkers.
  • You have an idea that you’d like to discuss and test, but might not ever intend to ship.

As a side note, the GitHub.com code base has 50% more pull requests than issues:

Bottom line? Pull requests are cheap and effective. Create them early and often.

4. Discuss your code

You can define a pull request a few different ways, but first and foremost it’s a discussion around code. Code review. The best code reviews (and thus, pull requests):

  • Have a limited set of changes
  • Specifically at mention individuals or teams
  • Include before and after screenshots, if dealing with visible front-end changes

There’s no harm in creating lots of pull requests for discussion. If you’re concerned about pushing unfinished work, let people know you’re not yet ready for feedback or merging to master. Two easy ways are to preface your pull request title with WIP: or to include a row of :construction: emoji in the opening comment.

Bottom line? Make it as easy as possible for your peers to help you ship your code.

5. Shipping it

When it comes to deploying or shipping your code for GitHub.com, you have a few options:

  • Branch deploy: deploying your branch temporarily to production in place of master.
  • Branch lab deploy: deploying your branch to a specific server, which when deployed, gives you a unique URL (e.g., hi_mom.branch.github.com).
  • Merging to master: merge your branch via the merge form on your pull request. Your branch is merged, tests are run, and master is redeployed with your changes to production.

The best thing to do is use branch lab because you get a real URL you can share with folks around the office. URLs are the best way to drop a link into Campfire to invite folks to view some changes. Also, there’s basically no limit to how many branches can be deployed on branch lab.

When you’re changes have shipped—meaning, they’ve been merged to master—you delete the branch. GitHub will automatically prompt you do to so after merging to ensure your list of branches stays lean.

Bottom line? When you’re ready to ship, test your changes in an isolated branch lab, then merge to master.

Shoutout to Hubot

Hubot is our Campfire bot that literally does (almost) all the things. Find Google images, remember things, run tests, and most importantly, deploy code. When I’m ready to deploy code, I just pop into Campfire and tell Hubot to get to it:

bash /deploy github/hi_mom to branch-lab

Hubot will automerge master if there are new changes not in my branch yet, run tests again, and then deploy my branch. If my tests fail or haven’t yet finished running, Hubot tells me that right in Campfire.

More reading

If any of this interests you, definitely check out some other articles from fellow GitHubbers:

Continue reading...

Dream on

This morning I was mentioned in a brief Twitter conversation, and because Jeffrey is the best, I feel obliged to reply.

I encourage you to read the mentioned post by Elliot Jay Stocks. In it Elliot asks the question, Why have today’s designers stopped dreaming? Between the article and the tweets, there are two topics I’d like to comment on.


First, Brendan blames—among other unnamed things—frameworks. Consider my interest piqued.

While Elliot directs his post towards the craftsmen—those swinging the tools—Brendan throws the tools themselves under the bus. He’s not alone in that line of thinking. Lots of folks hate on today’s frameworks, design tools, and the like. Usually that dislike comes out of personal preference or limited experience. That doesn’t invalidate anyone else’s use of those tools though, and we’ll all do well to remember that.

Let’s consider another “framework” for a moment—iOS. Is the most important operating system of the last decade to blame for a stagnation in app design and creativity? Some might say so, but have you seen the amazing apps that are being built on iOS? They’re fucking astounding!

Are frameworks the same as a mobile operating system? No, but they serve a familiar role—abstraction of common aesthetics, behaviors, and components with a focus on documentation. As absurd as it might sound, it’s hard not to see at least some similarity between the two.

Are these frameworks and other tools impervious to criticism? Definitely not. (Have you seen the number of issues against Bootstrap? It’s over 13,000!) However, it’s important to acknowledge that amazing things can be done with just about any tool if you have the right mindset.

Bottom line, the tools aren’t (completely) to blame.

Web workers

Second, from the article:

The web right now is a beautiful place. Web design has matured as an industry and the technology now enables us to create whatever we might dream of in HTML, CSS and JavaScript. But it’s clear that laziness amongst designers has never been more rife.

Thousands and thousands of cookie-cutter sites litter the internet, each one drawing just a little too much influence from the last. The blame is not to be laid at the feet of sites that provide actual website templates, but at the feet of professional designers who are churning out ‘bespoke’ sites that might as well be templates.

I dare say what we’re witnessing, and what Elliot and Brendan are referring to, is not laziness. The web design and development community is in a completely different place from when we got started.

We’ve been doing this stuff for 10, 15, or more years now. Those lazy designers you’re seeing? They’re lawyers, stay-at-home dads, bored teenagers, interior decorators, anthropology majors, teachers, and more. And they all just learned HTML and CSS last Tuesday afternoon while we were all eating our burritos and playing video games at work. (Hi, that’s me in case you didn’t realize.)

Today’s web is filled with millions of people who don’t make websites professionally. They make them simply because they want to and the tools are in place so that they can. That’s fucking awesome!

This doesn’t account for everyone though. Are some designers lazy? Yup, and at times I’m definitely one of them. The site Elliot described? It might as well be any number of the example templates that come with Bootstrap. And I’m perfectly okay with that.

Right or wrong

Elliot and Brendan aren’t wrong. There are lazy designers and developers out there, and tools and trends can make it easier for folks to be lazy. At times, I’m one of those lazy designers. Does that make any of us right or wrong? I don’t think so. Can all of us do better? Most assuredly.

Using design trends helps people. We find out what looks good doesn’t always feel good. We find out that some tools don’t always work for every job. We find out that performance and documentation are more important than your own visual preferences. Design trends, frameworks, and the like are, among other things, learning tools. Let’s keep that in mind.

Sing with me

Everything I do in my work at GitHub and on Bootstrap is dedicated to folks who want to make awesome stuff on the Internet. My dream is to help awesome people do awesome shit. Nothing else gets me more stoked out of my mind than that. I get goosebumps thinking about how much the web has changed and how we can continue to shape it just by writing code and sharing our experiences.

Designers didn’t stop dreaming. We just have millions of people dreaming dreams different than our own. Let’s encourage and foster that by enabling these people, and ourselves, to do more—and to do better. And of course, to dream on.

Continue reading...

Including CSS in Jekyll

Jekyll is a blog aware static-site generator. It’s great for building simple pages like Code Guide or blogs like this one. Lately, I’ve been a big fan of Jekyll’s include functionality.

Now, most folks use _includes for standard partials like a site’s header or footer. Lately though, I’ve been using them to easily include CSS dependencies for fewer page requests.

Say you have three CSS files to include in your Jekyll project. Normally you’d do something like this:

<link rel="stylesheet" href="site.css">
<link rel="stylesheet" href="font-awesome.css">
<link rel="stylesheet" href="syntax.css">

With Jekyll, you can turn that into one file during site generation with includes and YAML front-matter. Here’s an example Gist:

The front-matter tells Jekyll to treat this page as a buildable file rather than simply another asset to copy to the generated _site folder. With that in place, add any _includes you like, and run jekyll serve.


Continue reading...