Behind Gumroad’s New Design System
For Black Friday 2021, we wanted to release a site-wide rebrand to replace our previous, ten-year-old design with something much more modern. Our goals were for it to not only be exciting and new from a visual perspective, but to also make use of progress in web tech and accessibility.
On Black Friday, we successfully released our newly created design system, and since then we’ve incrementally migrated the rest of our website to use it. This has resulted in noticeable improvements to file size and accessibility across the board.
Gumroad is over ten years old.
Every decision we’ve made since then has been based on a set of assumptions that our CEO, Sahil, made back then.But assumptions and reality drift apart over time. This is not a phenomenon specific to Gumroad; ideas and requirements change as our culture and technology does. Software engineering moves quickly, and there are new things to learn every day.
Our approach for the last ten years has been simple: What’s the best use of our time, what’s the most efficient change we can make, to improve the lives of our creators? As an engineer, I always consider efficiency. When implementing a larger change I first ask myself whether it would be less expensive to change the existing implementation, or whether a larger, more fundamental refactor (read: writing it from scratch) would save time and effort in the long run. This is more art than science; often, both are valid options, and the only thing helping me decide is my experience.
But with Gumroad’s design system, the choice was clear.
After ten years of CSS written to solve the problem of their day, we started 2021 with 140 CSS files totaling over 30,000 lines of code. And while Gumroad is certainly complex, it’s not “30,000 lines of CSS” complex. Our stylesheets had become inflated by their lack of real structure, multiple implementations of the same patterns and components, and no consistent usage of variables or design patterns.
With all this in mind, and with the exciting task at hand being a complete visual overhaul, we decided to replace all of the existing CSS with a completely new set of stylesheets, considering all of the new requirements, standards, and browser capabilities of 2021.
A New Design System
This clean slate meant complete freedom on how to structure the new design system and its files. We had a lot to consider, as there had been much progress since our inception in 2011:
- Accessibility as a whole has recently and rightfully become a much more popular topic on the web - WAI-ARIA now provides a specification to communicate visual ideas to screen-readers, allowing developers to make a website that is visually exciting and innovative while still being understandable to visually impaired users.
- HTML had introduced multiple new semantic elements conveying meaning and natively encapsulating functionality. These have implicit accessibility benefits as browsers can render them however is most beneficial given the context and provide support for mouse, keyboard and touch inputs, and they are natively understandable to screen-readers and other accessibility tools.
- CSS had grown to support many new technologies - grid layouts now provide consistent styling of child elements, advanced selectors allow supporting and enforcing a specific structure, and animations have become so much easier to create and work with.
Aside from the progress in web technologies, there were also a lot of new design frameworks to pick from, with the most popular currently being Tailwind (sold via Gumroad!). Most of these frameworks offer a pre-built component gallery and/or a collection of utility classes to cover common use-cases of CSS.
We ultimately decided against using any of these frameworks, and to instead build a custom component system from scratch in (S)CSS. We had a great opportunity to think about Gumroad’s design from the ground up, and we did not want to taint that with someone else’s assumptions. We love working with HTML, CSS, and web standards. And thanks in large part to the progress mentioned above, we didn’t need much more than that.
Our new component system needed to be strict and to cover every building block of our application, allowing for and providing exactly one way of implementing a certain pattern, exactly one solution for any given problem. We decided to prohibit any page-specific CSS files in our new design system. Everything was going to be a component, and our entire functionality was to be composed from them going forward.
The driving principle of our new design system is consistency, and when implementing it, we took great care to always match the intent of the design. Every selector, every state, every property has been modeled after its designed intent, and exceptions modeled as such. To achieve this, the new design system breaks with some common directives in design and component systems:
- We directly style built-in HTML elements such as button. Semantic elements have accessibility benefits, so we want to enforce their usage, and we want all of our buttons to look the same. Modelling selectors after their intent means not being afraid of being general. If there is ever an exception, we take care of it in the exception, not by being defensive.
- We avoid using classes as much as possible. Where no semantic elements are available, we try to correctly use ARIA roles, to maximize accessibility. If none are applicable, we try to only use one class to select the component itself, consciously enforcing a certain DOM structure within them by selecting children using relative selectors rather than classes. This will allow us to make even sweeping changes with ease going forward, as every usage of a component is guaranteed to be the same. It also helps accessibility tools such as screenreaders, as classes are invisible to them, while a clear structure helps them understand association and ownership of elements.
- We use inline CSS to describe exceptions, and meaningless and specific layout containers. This is probably the biggest departure from the usual procedure in CSS frameworks and code styles, which tend to prefer using utility classes in such cases. However, such a class would not fit into our component-based design system, as it doesn’t encapsulate anything meaningful - nor would it have a real benefit over inline CSS.
Replacing the Engine Mid-flight
We began by defining a basic look and feel in terms of color schemes, fonts and sizes, and borders. These would see some changes during the later stages, but having that system in place from the beginning and building upon it was crucial. We then went through each page individually, and created a component system that was extensive and flexible enough to cover all the functionality and states we were going to need, and that made sense from both a visual and technical perspective. We then codified these components in Figma, making sure to cover all possible states and interactions, and creating a universal truth for what Gumroad should look like.
Eventually, our design system reached a sufficient level of maturity to begin implementing it in code. To do so, I used Storybook.js to create interactive demonstrations of each of these components including all of their states. This has since grown into a component gallery of about 40 components, providing a full overview of all available building blocks to both designers and developers.
Once most of these components had been implemented, we began the work of updating Gumroad’s existing pages to use them. We knew that despite the planning and consideration we had already put in, there were going to be a lot more changes to the component system during this period. All of the work we do at Gumroad is iterative; we start with something that works, and then continue working on it to make it the best it can be. We continued improving the design system as we applied it to our pages as we saw what didn’t fit and what was missing, noticed edge cases we needed to support, and found compatibility issues to respect.
It was obvious from the beginning that this project was going to be too big for our usual process of working not in teams, but as individuals on tasks that we work on autonomously from feature design to completion. This workload was going to be too large for one person to work on, and we quickly realized that getting it done in time (we wanted to have it ready for you in time for Black Friday, after all!) was going to require collaboration across all of our engineers.
With everyone at Gumroad being a part-time contractor used to working autonomously and fully remotely, management is not a concern or requirement that often comes up - it’s usually limited to creating and prioritizing tasks. This project was going to require more coordination, but to allow us to still follow most of our usual work processes, we still split the workload into chunks (usually by page, but there were some exceptions) that were small enough for one engineer to work on. This allowed us to approach even an undertaking of this size while maintaining our asynchronous work culture.
From a technical perspective, we had two distinct options to be able to work on the rebranded design while allowing the old design to continue functioning:
- Split the codebase by creating a separate branch that the redesign was going to live in, keeping it entirely separate from the old design. This was going to mean only one version of the design would have to be functional at once.
- Work on the redesign in the same branch, ensuring that our changes were additive, leaving old classes and functionality untouched.
Ultimately, we chose the latter option, as while maintaining both designs and keeping them functional at the same time was going to take extra consideration, it was necessary to be able to work on it iteratively.
By keeping everything in one code base, changes (and bug fixes!) were automatically going to apply to the new version as well, rather than having to deal with a massive and dangerous merge between the two versions once we were ready to release the rebrand. Most importantly, this allowed us to release a partial version of the rebranded website, with only the pages that truly were good enough to show you while working on the rest iteratively, rather than having to rush the whole thing in time for Black Friday.
Aside from management and code maintenance, the most important consideration when implementing the rebrand was consistency. We had to make sure that the design system was being applied everywhere and correctly, that any additions or changes to the design system were consistent with the rest, and that everything came together to form our new look and feel.
To ensure this, I began by creating a document outlining the principles that were applied while creating the design system, and the process of migrating a page to use it. Information symmetry is a very important part of our work at Gumroad - we try to make sure everyone has access to everything where possible, including the reasoning for decisions, allowing them to understand it, reproduce it, and give feedback where appropriate.
As part of that process, every pull request was to be reviewed personally by both our Head of Design and myself, and we made sure it matched the ideas and reasoning we applied when initially creating the design system. This was not because we believed our ideas were objectively correct, but ensuring consistency during these early stages was going to allow us to make improvements later while being certain we weren’t overlooking or forgetting anything.
This was a considerable amount of effort, and during the two months of the main rebrand effort, both of us worked far more than our usual part-time hours, and I personally reviewed over 200 pull requests. But it paid off - we now have a working and consistent design system that’s being used across our entire web application. As with any part of Gumroad, we will continually improve it, and the strict and consistent design system will allow us to make changes of any size with ease going forward.
Working at Gumroad
As a side note, I have been working with Gumroad for over nine months now, and it has been an incredible experience. The autonomy and freedom we have in our work is unlike any other company I know of, and it allows us to prosper and grow. In the process of creating this new design system and leading its implementation across our entire website, I was faced with many new challenges - but I never felt pressured. At Gumroad, mistakes are learning opportunities, not something to be feared. I’m very grateful to Sahil for fostering this culture, as I am for all the other amazing people I work with. I’ve also been allowed to livestream my work recently, and it has been a wonderful experience. I personally plan to stay with Gumroad for a long time, but I still hope that other companies and their stakeholders will eventually realize the benefits of such an open and productive environment, as well.