InVision presents

Design Systems Handbook

by Marco Suarez, Jina Anne, Katie Sylor-Miller, Diana Mounter, and Roy Stanfield

A design system unites product teams around a common visual language. It reduces design debt, accelerates the design process, and builds bridges between teams working in concert to bring products to life. Learn how you can create your design system and help your team improve product quality while reducing design debt.

Go to Chapter
Introducing design systems
The power of scale

Repetition and reusability make scale possible. InVision’s Marco Suarez takes you back to the foundations of component-based design and the many ways design systems enable scaling. He also addresses a few common misconceptions about design systems.

Go to Chapter
Go to Chapter
Designing your design system
Step by step

Starting can be the hardest step. Design systems expert Jina Anne walks through what to consider as you start out. Involve the right people, find the right model, add the right pieces—and you’ll be well on your way to establishing a successful design system.


Go to Chapter
Go to Chapter
Building your design system
A strong foundation

Building a flexible, maintainable, stable, scalable design system creates a strong base for your product design team. Etsy’s Katie Sylor-Miller shares foundational knowledge learned building design systems across cross-functional teams.


Go to Chapter
Go to Chapter
Putting your design system into practice
Better together

Encouraging adoption of your design system forges connections and creates champions across teams. GitHub’s Diana Mounter lays out practical strategies for sharing design systems and growing adoption, including examples from her experience.


Go to Chapter
Go to Chapter
Expanding your design system
More than the sum of its parts

Components form the core of a design system, but teams can align around much more than components. Marco Suarez outlines how teams can round out their systems with vision statements, design principles, voice and tone guides, and more.


Go to Chapter
Go to Chapter
The future of design systems
To infinity and beyond

Design systems play a huge role in shaping our present, but we may only be scratching the surface. Airbnb’s Roy Stanfield explores a bold future of intelligent, adaptive, context-aware systems that could further accelerate design’s possibilities.

Go to Chapter
Go to Chapter
More resources

Design systems continue to evolve, and every company’s system can offer something to our collective knowledge and understanding. We’ve curated a list of publicly available design systems and resources to help you continue your exploration. 

Go to Chapter

Building your design system

A strong foundation

by Katie Sylor-Miller, GitHub

Modern design systems are the result of many years of evolution in the way we write front-end code. When I started my career, most sites were built with single-use, inefficient, fragile, and inconsistent front-end codebases. Through hard-won experience and many years of collaboration and iteration, front-end developers have established more sophisticated practices for writing and organizing our code. Now, there is an explosion of front-end frameworks and tooling to help you write better, more maintainable HTML, CSS, and JavaScript.

This represents an exciting paradigm shift in front-end development, but the number of choices available can be overwhelming. A cursory glance at the table of contents for Cody Lindley’s Front End Developer Handbook 2017’s section on tools reveals a bewildering array of considerations. I couldn’t possibly cover all of the technology choices available—the factors that go into your decision-making will be largely situational, and this is only a chapter!

Instead, I’ll save you the headache of attending the school of hard knocks by walking you through what I’ve learned from building and contributing to 3 different design systems. First, I’ll cover the technology-agnostic foundational principles that should guide the development of your design system. Then, I’ll focus on some common pitfalls and how you can avoid falling prey to them. Throughout, I’ll introduce you to some of the tools that will help you along the way, but remember this: Your technical approach doesn’t matter as much as creating a living, breathing system that’s flexible, maintainable, stable, scalable, and successful in the long-term.  


Regardless of the technologies and tools behind them, a successful design system follows these guiding principles:

  • It’s consistent. The way components are built and managed follows a predictable pattern.
  • It’s self-contained. Your design system is treated as a standalone dependency.
  • It’s reusable. You’ve built components so they can be reused in many contexts.
  • It’s accessible. Applications built with your design system are usable by as many people as possible, no matter how they access the web.
  • It’s robust. No matter the product or platform to which your design system is applied, it should perform with grace and minimal bugs.

Let’s take a look at each of these principles in more detail.


Your first, most important task when starting out is to define the rules of your system, document them, and ensure that everyone follows them. When you have clearly documented code standards and best practices in place, designers and developers from across your organization can easily use and, more importantly, contribute to your design system.

Code style guides

Code style guides provide the grammar rules of syntax and semantics for your code. Code syntax is the set of rules for structuring and formatting your code (e.g. curly braces always go on a new line). Code semantics provide the rules for making your code understandable (e.g. alphabetize CSS property declarations). But don’t get bogged down fighting pointless wars over tabs versus spaces. The most important thing is to end up with consistently written code, not to achieve theoretical perfection!

Automating code style

To enforce your code standards and achieve consistency in your system, help your contributors write code that follows the rules through linting and tooling.

Linting is an automated process of analyzing code and raising errors when code either doesn’t adhere to your syntax rules or is broken, buggy, or malformed. Linting tools such as CSSLint or StyleLint for CSS, and JSHint or ESLint for JavaScript, can be run manually as part of your local development process, as an automated pre-commit hook before code is checked into source control (the best option), or run as part of your build process.

Code editor configuration

An often-overlooked but important corollary to linting is providing an Editor Config to enforce code style in your editor(s) of choice. (figure 1) provides a cross-platform format to define stylistic rules for most code editors and IDEs, so you can automatically convert your tabs into spaces—thus ending the tabs versus spaces war!


Your design system should live in a source control repository independent from your main codebase. Although it will require more work to get up and running, a separate repository brings many long-term benefits:

  • It enables versioned releases of your code (more on this later)
  • It allows you to share code across multiple teams, products, and codebases
  • It forces you to develop components in isolation so they’re not tied to a single use case
  • It provides infrastructure for a robust front-end testing architecture
  • It forms a foundation for a living style guide website

A standalone design system repository functions as a single source of truth. There is only one place where components are defined, which then gets shared into other codebases as a discrete dependency. Because all usages point back to a canonical implementation, changes in a single place propagate through the entire system.

Ideally, all of the code for each component within your system is co-located: CSS, JavaScript, HTML templates, and documentation all live in the same place, possibly the same directory. If you’re using React with CSS-in-JS, each component may even be encapsulated in a single file. The closer the pieces are to each other, the easier it is to trace and manage dependencies between bits of code, and the easier it will be to update and maintain.


Successful design systems are highly reusable. Bootstrap, the most-used front-end library of all time, powers hundreds (if not thousands) of websites because it was architected with reusability in mind. Writing components to be reused in multiple contexts is vitally important, yet hard to do well—make components too focused for a single use case or too inflexible, and users will end up creating their own patterns.

To be reusable and scalable, patterns need to be modular, composable, generic, and flexible.

  • Modular components are self-contained with no dependencies
  • Composable components can be combined to create new patterns
  • Generic components can handle multiple use cases
  • Flexible components can be tweaked and extended to work in a variety of contexts

Modular CSS architecture

Reusability and scalability in design systems begin with taking a modular approach to your code architecture. CSS, however, is not inherently modular. So over time, systems like SMACSS, OOCSS, and BEM have added structure and modularity to CSS. More recently, CSS-in-JS approaches such as Styled Components have solved the problem by defining CSS properties in JavaScript code structures.

Whether you use one of these systems or roll with your own, the fundamentals of any good CSS architecture are the same:

  • It has clear naming conventions for components, variations, and utilities
  • It’s tightly-scoped and has low-specificity CSS that limits unintentional side effects
  • It has utility classes that allow you to modify styles in a managed way
  • It has rules for building modular, composable, generic, and flexible components

To learn more about architecting CSS so that it meets these criteria, I highly recommend Harry Roberts’ (figure 2), then adding this type of documentation to your system.


For too long, accessibility, or a11y, has been misunderstood as building sites for a small group of users of assistive technology—a blind person using a screen reader—and far too often dismissed as too complex, too time-consuming, or “not our customers.” Accessibility, however, is not just for a single, small group, but for an estimated 15% of people worldwide (56.7 million people in America alone) with a wide spectrum of permanent or temporary visual, auditory, motor, and cognitive impairments.

Thankfully these attitudes are changing and our industry is embracing a more inclusive definition of accessibility. Making your site accessible to users with disabilities improves the experience for everyone who visits your site. If that isn’t enough motivation, improving your site’s accessibility can help improve SEO, and it’s becoming increasingly more important from a legal standpoint to avoid costly lawsuits.

In a landmark case against the grocery chain Winn-Dixie, a federal judge ruled that websites are subject to the provisions of the Americans with Disabilities Act (ADA). If you’re just learning about accessibility, there are a lot of resources to help you get started. I recommend reading the introductory articles from the W3C’s Web Accessibility Initiative (WAI) WebAIM, and the A11y Project. You can inspect the current state of your site using Tota11y, an a11y visualizer bookmarklet by Khan Academy. Starting an accessibility practice where none has existed before can be challenging, but when you leverage your design system, it’s easier than you might think.

Enforce a11y with your design system

To ensure everyone at your organization builds accessible sites, features, and apps, enforce accessibility best practices in your design system code.

  • Test your color usage against established color contrast guidelines (figure 3).
  • Build components to be keyboard and screen reader accessible by default. The Ebay Accessibility MIND pattern library is an amazing, thorough resource to help guide development of accessible components and best practices. Encourage contributors to build according to these guidelines and test their code using keyboard-only navigation and assistive technology devices like screen readers.
  • Include in your documentation code standards and guidelines for common a11y best practices such as using larger, legible text sizes, always associating a form field with a label, and properly adding alt text attributes to images, to name a few. Salesforce’s Lightning design system and Shopify’s Polaris are great examples of accessibility guidelines in practice.

These accessible practices improve usability for everyone by making it easier to view, interact with, and navigate a site, improving form completion rates and reducing user mistakes.

Use the power of your single source of truth to create a foundation for accessibility, thus relieving some of the burdens from product teams. It’s much easier to build in accessibility from the start than to bolt it on after a feature has been designed and built.


A robust design system has a strong foundation of tests behind it. Testing provides confidence in your code, which facilitates adoption. Users will know that they can upgrade or change their UI without it breaking in unexpected ways. Additionally, your design system is uniquely positioned to form a foundation for robustly testing your front-end code.

Test your design system instead of your complicated UI

Keeping tests up to date for pages, applications, and features—especially on a rapidly changing site or one with heavy experimentation—requires a lot of work. Tests get out of date quickly! You can narrow the scope of your tests and gain higher levels of confidence in your site-wide front-end code by heavily testing your design system components. You already need to generate example code for the different states of each component for your documentation—use those as your test fixtures.

Types of tests

There are 4 types of tests used for ensuring stability in your design system:

  • Unit testing: These tests verify that small units of code (usually individual JavaScript functions) behave as expected. Unit tests execute functions with a set of predefined inputs, then verify that they return the expected output. Some popular frameworks to use are Mocha, Jasmine, and Jest.
  • Functional testing: In functional tests, examples of your code, or “fixtures” are run in a virtual “headless” browser, then tested by performing simulated user actions, and checking the new state of the browser for the expected result of those actions. Functional testing frameworks include Nightwatch, Protractor, and Casper.
  • Visual regression testing: These tests help catch unintended visual changes to component styles. The test framework takes screenshots of your fixtures both before and after the changes, then compares them using an algorithm to detect visual differences. There are open source frameworks like Wraith, Gemini, and BackstopJS, as well as paid services like Applitools and Go to Kevin Lamping’s excellent resource Visual Regression Testing for more information and options.
  • Automated accessibility testing: Leverage tooling to ensure that your components are accessible. Some options for running automated a11y audits are Paypal’s AATT and a11y by Addy Osmani, and aXe by Deque Systems.

Common challenges

No system is ever perfect. You will make decisions that you later regret, no matter how much time you put into designing your design system. You can, however, anticipate issues that arise as your system grows, and work to avoid or mitigate their effect on your project. There are 3 common challenges I’ve seen arise in multiple design systems:

  • Keeping documentation up-to-date with your system code
  • Handling breaking changes
  • Avoiding performance degradations

Let’s look at each of these concerns in detail.

Maintaining documentation

The first time I built a front-end component library, my team decided it would be easier to create a documentation website with a codebase separate from our application. In hindsight, this decision broke the cardinal rule of Don’t Repeat Yourself. Whenever a component changed in our main codebase, we had to remember to actually update the documentation, then do the tedious work of duplicating the changed code in 2 different codebases. Unsurprisingly, our documentation got out of date almost immediately!

Learn from our mistakes by reducing the distance between your documentation and code and using automation.

Minimize separation between library code and documentation code

Earlier in the chapter, we discussed storing your design system code in a separate repository that functions as your single source of truth. When documentation and code are co-located, it’s more likely that you’ll remember to update the documentation when a component changes. Consider adding a pre-commit hook to your design system repository to warn contributors when their code adjustments don’t also contain updated documentation files.

Automate documentation

Start by documenting your system using simple, human-readable files written in markdown, co-located with each component. Github is already configured to render and display any file named when you’re viewing a folder’s contents—you might not need a flashy website at all!

If and when you do decide to create a full-featured documentation website, use automation to simplify the process. Instead of creating a new codebase for a separate website, use a tool that will auto-generate documentation for you—there are lots to choose from—reducing the amount of structural HTML you need to write and maintain.

Handling change

As adoption grows and your design system becomes more widely used, you will invariably realize that you didn’t get it all right the first time, and you will need a plan to handle breaking changes. A breaking change is a situation where necessary changes to a component’s code will break existing usages of that component or class. The Morningstar design system provides guidance to contributors on what is considered a breaking change. If mishandled, breaking changes can be a major pain point for your users.

The wrong way: duplication

Initially, all of the CSS and JavaScript for Etsy’s Web Toolkit lived in the same monorepo with the rest of the team’s site code. This meant that whenever someone made a breaking change to a component, their commit making the change had to also contain fixes and updates for every single usage of that component. At first, when just a small team built and used the system on a subset of pages, finding and making these changes was relatively easy. But as adoption spread throughout the company, this quickly became unmanageable.

It became such a headache to make major structural changes to existing components that our team at Etsy started to duplicate and deprecate—when we refactored our Tab component to make it fully accessible, we created a new component named “Tabs2,” and deprecated “Tabs” in the hopes that teams would take on the work to upgrade their code. But without clear guidance on how, why, and a timeline stating when to upgrade, most uses haven’t been updated to use the new component. This kind of duplication is a code maintenance nightmare.

The right way: versioning

Breaking changes are easier to manage if you store your design system code in its own source control repository. This gives you the ability to do versioned releases of your code, which can be shared with other projects. Git allows you to tag a commit with a release version number, and package managers like npm and Yarn allow you to package up and publish multiple versions of your design system code.

With versioned releases, the adopters that integrate your design system code can target a specific version as a dependency and control when and how upgrades to new versions are handled. Make sure to publish release notes detailing changes so other teams can learn how upgrades will impact their codebase and better plan for upgrade work in their project timelines.

Avoiding performance issues

As a design system grows over time, generally so does the file size of assets sent over the wire on each page. This can negatively affect your site’s page load performance, which in turn negatively affects your company’s bottom line. Help the products built on your design system avoid performance issues by taking a mobile-first approach and build your system with modularity in mind.

Mobile first

Poor page load performance will have the largest negative effect on mobile visits. According to statistics from Google and Akamai, more than half of mobile visitors will abandon pages that take longer than 3 seconds to load, yet the majority of mobile sites take longer than 10 seconds to load. As mobile traffic overtakes desktop, speeding up your page’s performance is more important than ever to give you a competitive edge.

Build your design system mobile-first—test early and often on real devices with real hardware and a real network connection so you can understand the experiences of real users.

Leverage modularity

Initially, it made sense to bundle all of the Etsy Web Toolkit components and utilities into single files for CSS and JavaScript. While this is useful for prototyping, it adds unnecessary weight to production pages that don’t use all the components. Now, we’re working to avoid performance problems by better using the modularity inherent in the system. To do this, we are:

  • Deciding on a set of core components and utilities that are most frequently used. This base file will be included on all pages that use the design system and can be cached by the browser across page requests to improve load times.
  • Ensuring that all components are fully modular with no cross-component dependencies (unless they are explicit and managed by the system).

Packaging and sharing the system’s code so that it can be consumed as individual CSS and JavaScript modules added as dependencies only when a component is actually used on the page. We use an in-house system to define dependencies in our front-end code. Build your design system modules so they work with the dependency manager that your team uses. Webpack is a popular option.


Design tokens

For most of this chapter, I’ve focused on building design systems for web applications and sites. However, that’s not the full picture. Modern organizations face unique challenges with their design systems at scale. Today, we build for multiple web and native platforms that need design consistency. Larger organizations may have multiple sub-brands that want the shared support, functionality, and organization that a design system brings, but each needs a different, brand-aligned look and feel. The Salesforce UX team introduced a solution to both of these problems: design tokens (figure 8).

Cross-platform sharing

Design tokens are a way to abstract design details like colors, fonts, rounded corner radius, etc., into a format that can be shared across platforms using Salesforce’s Theo tool. Instead of defining your main brand color as a SASS $variable in your web app, a UIColor in your iOS app, and a textColor in your Android app, you define a single design token in a shared JSON file that gets compiled into platform-specific code (figure 9). Decide to change all of your rounded corners from a 3px to 5px border-radius? Change the value once in your tokens file, and it propagates to all of your apps automagically.

Multi-product theming

You can also use tokens to “theme” the same structural styling for multiple brands. One brand wants orange buttons and the other wants blue? No problem! You can define different token values for each brand, then combine each to the same, base CSS to output themed versions of your design system. That way, all of the classes are the same, and all of the accessible JavaScript functionality you worked so hard to build can be used as-is with no modification for each brand.


Systematizing your front-end code benefits everyone in your organization: developers move faster, designers don’t have to reinvent the wheel, and ultimately, your users have a better experience. But starting out can feel overwhelming!

Thankfully, there is a wealth of resources and a growing community of folks sharing their own best practices to help you build your system. Anna Debenham’s Styleguide Resources lists nearly 500 public design systems/style guides/pattern libraries to use as inspiration. While they look and feel very different, each shares a common goal and is built upon foundational principles that our industry has developed through many years of trial-and-error.

A flexible, maintainable, stable, scalable, and successful design system begins with a strong foundation that goes beyond frameworks or tooling. If I’ve learned anything in my career, it’s that the only constant in front-end development is change. Chances are, within a few years, the technology driving your front-end will look very different than it does right now. If you build for the long-term and plan to handle change, then you can implement new, better practices as your system grows.

That’s not to say you should aim to create another Bootstrap right out of the gate. Even if your team can only implement a few of the best practices we’ve discussed in this chapter, it’s still worthwhile—some of the techniques I recommend haven’t yet been implemented in the design system that I work on every day! Design systems are not a one-and-done thing, but a continual process of iteration and change as we make mistakes, learn from each other, and create new and better approaches to front-end code.


The future of design systems

To infinity and beyond

by Roy Stanfield

I find it exciting to see design systems empower design teams to scale and consistently produce solid products, but I know we’re only scratching the surface of our potential. There’s so much more we can accomplish.

At Airbnb, we’ve been pondering how we might push our design system in new directions, and we’re inspired by design-forward companies that share our desire to craft the future of design systems.

In this chapter, I want to introduce you to a new way of thinking about design systems. Design systems can transcend the walls of a single company to exist as shared standards and customizable tooling with help from the open source community, which can accelerate development and eliminate the need to start systems from scratch. If we’re really bold, we could be creating adaptive, intelligent systems that are context-aware and compose themselves—reducing our workload and ultimately unlocking AI-powered design.

But, I’m getting ahead of myself. Let’s start with nuts and bolts.

Building a common foundation

In his 1998 essay Interchangeable Parts, Tim Sheiner examined the historical standardization of parts for physical products, and predicted how this will play out for digital products.

A designer’s familiarity with the concept of a design system is based on the systems they’ve encountered, what platforms they’ve been tasked to support, and where they’ve worked. Books like this one help us converge on a high-level definition for design systems, but a more rigorous definition will ensure the utility and flexibility of our work.

Finding a standard that supports shared goals will involve decoupling a design system from its implementation, cataloging common UI and associated states, and more strictly defining design primitives and components. This could then be expressed in a file format that’s able to define a component or design system more completely.

An example of differing goals

Currently, existing systems reflect the specific needs of the companies that created them. Since each company is building an entirely independent system, design system development starts from scratch—possibly with help from a web toolkit like Bootstrap, relying on the internal knowledge of the team, and only focusing on top-level needs. As a result, even the best systems contain flaws and lack the necessary tooling to speed development and track results. And if a company’s priorities shift, its design system must shift, causing another section of the design system to be built in the same limited way.

For example, one of the reasons Airbnb created DLS was to minimize and sync differences in UI between our supported Android, iOS, and web platforms. In The Way We Build, VP of Design Alex Schleifer writes, “Universal and Unified define the system’s approach we apply when defining patterns. Is it part of a greater whole? Does it work across devices?”

In our idealized vision, a mockup easily ports between platforms—creating a better design and development experience. This cross-platform UI would give Airbnb guests and hosts alike the same end-product experience as if they jumped between mobile app and desktop web.

In contrast, supporting multiple device platforms was initially less of a concern at Etsy, where the main priority was to scale its web platform. During my time there, the team built the web toolkit with the core website as its primary focus. Later, Etsy expanded upon its toolkit to support different branding elements for other internal web initiatives. Karyn Campbell describes what it was like modifying the Etsy design system while making Etsy Studio. “While we made a conscious decision to depart in some instances with the UI in order to birth this new brand, we also retained many underlying components that our design systems team had created.”

A priority at Airbnb was having the same functional and visual voice across platforms. A priority at Etsy was to support multiple web products with varying brand initiatives. Both were valid needs. A shared standard for design systems would need to ensure a solid foundation so that both these and other real-world priorities could more easily be achieved.

Gathering examples of different design system priorities will help create a checklist to make sure your design system standards address real concerns. Any company adopting these suggested standards could be assured their design system development focuses on immediate company needs, as well as adhering to standards they plug in to a growing body of open source code and tools that support most operational transformations that could be encountered.

But what should be in the design system standard?

Imagine a tool that can specify which design primitives, (e.g., fonts, spacing, color—more on that below), components (and their states), platforms, and what documentation and testing are needed to have a fully formed design system. The tool would also allow the designer to specify which components were not yet needed and which platforms could be added later. With this tool, a designer would have a framework stating what aspects of the design system were completed or outstanding. A product manager could export documentation, and a developer could easily export UI and UI tests—no longer needing to translate UI from Sketch to code, or from web code to native implementation.

If created today, not only would this tool provide industry-wide savings, but it would start to standardize the low-level definition of a design system. Working backward, let’s now imagine what kind of definitions such a tool would need in order to exist.

First, decouple the design system from any specific implementation. We’re not creating React components (nor other web implementations), nor Android UI, iOS UI, or even Sketch files. Instead, our system is an abstraction that can be deployed to any target implementation. We’re going to need a file format to describe this abstracted design system. The exported format could be rendered into views by open source modules specific to each target implementation.

Next, codify the definitions of design primitives and components so they are fully expressed in the design system format. Dang, .dsf extension is already in use! Guess we’ll have to settle for the .dang file extension!

Design primitives are the building blocks of a UI. These include specific predefined colors, fonts, spacings, and more. They are foundational visual elements that can be combined into components. Changing primitives is echoed throughout a given design system’s components, and doing so changes the overall feeling of a brand. Additionally, what are components? We’ll also need to codify those. Components are mostly views composed of design primitives and smaller components whose minimal internal logic is mapped exclusively to state and state change. Benjamin Wilkins, Design Lead on the Design Tools team at Airbnb, describes the difference between primitives and components in minute 7:00 of his talk, Thinking in Symbols for Universal Design.

Next, we’ll need to catalog all of the common UI components in use today. Just as a typeface may have its unique take on the letter “A” (the letter’s visual appearance may vary between typefaces while its meaning is maintained), a .dang file would have a text input component that varies in visual representation but not functionality. The catalog will need to group components with their accompanying states (selected, focus, on-tap, error, etc.) and detail interactions to distinguish between mobile, desktop, and TV UI.

What are the benefits of this catalog? To start, functional tests for common components could be easily automated through contributions from the open source community. In many cases, UI engineers would no longer need to write their own tests. The cataloged components would also enable a marketplace of boilerplate design systems that can be installed interchangeably, and against which custom UI can be built and substituted. This means bootstrapping the creation of every design system is no longer necessary.

Lastly, we need to allow for the evolution, growth, and extensibility of design systems built upon the shared standard. Just because we’re aware of which components are needed today doesn’t mean that we’re able to predict all the elements needed for future innovation. A process for modifying existing components or creating wholly new ones is in order. Thoughtfully standardizing our collective knowledge will produce a more consistent user experience, accelerate development, decrease investment needed from individual companies, and enable open source and collective development of next-generation design tools that conform to shared conventions.

Creating a single source of truth

The elements that make up a design system—principles, UI components, patterns, and documentation—create the human-computer interaction layer for our apps. Product designers and system designers are directly responsible for this layer, and therefore should own the design system and its representation in the codebase.

There are 2 hurdles to achieving a single source of truth. First, our current design tools are inadequate. Most only allow us to produce images of UI and prevent designers from achieving product level fidelity. Second, if the implementation of a design system is spread across multiple repositories (Android, iOS, React Native, React, etc.), collected in a Sketch file, and documented on a website, then there really is no single codebase to represent a truthful account of the system. Lacking a single source of truth, the design system—spread out over multiple codebases—becomes an amalgam of sources that easily fall out of sync.

Our tools

Designers use tools like Sketch, Illustrator, or Photoshop to draw pictures of UIs, yet these are actually just representations of interactive components that look different, behave differently, and contain different data depending upon the state of the app at a given time. As Colm Tuite notes in the article Design tools are running out of track. Here’s how we can fix them, “Think of the number of simple interactions which are commonplace in almost all of our products yet cannot be communicated through our design tools.”

Tuite then mentions interactions and states such as hovering over a button, focusing an input, checking a checkbox, and identifying scroll areas. He points out that our design tools aren’t prompting designers to think with product level fidelity, and so a designer’s work is usually missing some of its most important details.

Sketches of apps are then handed off to developers who have to translate them into working UI. Between the designer and the 4 developers that it takes to convert the design into Android, iOS, React Native, and React, it takes 5 different members of the team begin to bring the design up to product-level fidelity. Since the original sketch was missing details about state and interactions, a back-and-forth conversation between designer and multiple developers is needed to make the designs production-ready. And because the implementation is coded by 4 different humans, it’s likely that unwanted variation creeps into each implementation.

For similar reasons, many designers have focused on sharpening their coding skills for at least 1 platform. There are many advantages to this, but if you’re a systems designer creating components for cross-platform use, coding those components for a single implementation is not yet enough.

Multiple implementations

The attempt to reach a single source of truth is further complicated when working on cross-platform design systems. Jon Gold identifies places where Airbnb’s DLS workflow could be improved in Painting with Code.

At Airbnb, Gold has taken some exciting first steps toward solving this problem with his project React With this tool, layered Sketch files can be generated from the React codebase. This means components in the Airbnb React repo, which already have product-level fidelity, can be populated with real data and rendered to a Sketch file. It’s another reward for those adventurous designers willing to learn React!

It’s also a touchstone technology, pointing us toward understanding mockups not as the source of truth, but instead as another target for automated output. With these generated files, we get a clear picture of which components are sitting in the repo. Best of all, a product designer relying on Sketch does not have to change their workflow and can use more accurate files (generated by the codebase, not by hand) to compose their work. At last, we can have confidence in how the components look at product-level fidelity and in how these components behave with real data.

React is great because it syncs the React and React Native repos and Airbnb’s design system Sketch files. But what about the Android and iOS implementations? How can designers make sure these are in sync? React points the way, but we’ll have to go further.

Here, we can learn from tools and WYSIWYGs of the recent past like Dreamweaver and Interface Builder. Tools in this category allow users to combine elements of UI, hook the UI up to data and interaction, and then export deployable code. Unfortunately, these software produce code that’s not maintainable by humans, and so few companies use them as an official part of their process. Did these tools promise too much and deliver too little?

Luckily, design system components are simple views with minimal logic. (Learn more about views and MVC architecture here and here.) Unlike the promise of tools like Dreamweaver and Interface Builder, components are easily exported view files that developer partners can incorporate into existing workflows.

Solving 2 problems with 1 tool

To create a designer-controlled source of truth, we’ll need next-generation design system tools to enable the composition of components and to automate the output of the design system to any number of target clients (codebases, vector files, and documentation sites).

As outlined in the section above, if we standardize an export format that contains production-level fidelity for components, then other interpreter modules can be freely built to compile a single component file into all the various flavors of production code. Then, varied implementations of any given component would flow from a single source of truth and would plug right into existing workflows—saving resource-intensive and error-prone human interpretation of mocked UI. Product designers and design system designers would finally control the UI they have always been responsible for.

At Airbnb, we’re tackling this challenge in a variety of ways, including with Lona, our tool for defining design systems and using them to generate cross-platform UI code, Sketch files, images, and other artifacts. A highly experimental prototype, Lona represents our exploratory approach to discovering what’s next for design at scale. Taking a research-based approach to the future of design systems encourages experimentation and collaboration.

Intelligent systems compose themselves

If you’ve not heard of Alan Kay, make sure to look him up. He’s credited with inventing the graphical user interface, Object Oriented Programming, and—with his concept of the Dynabook—even the tablet. Given that design systems fit firmly inside of the world that Kay and his peers built, it’s worth listening to him.

Once the magic of design system standards enables both private and open source development for cross-platform use, design systems will most likely reach new heights of functionality and popularity. Whereas siloed development requires talented people to reinvent the design system anew for each employer, standards-based design systems might easily plug into a passionate community that will add capabilities to our nascent tools.

Taking inspiration from Kay and the PARC maxim—“The best way to predict the future is to invent it”—I’ll sketch out a stretch goal for the future of design systems and tools in the paragraphs that follow.

Virtuous cycle—plugging into the feedback loop

Often, our design systems contain components that aren’t tracked in any special way. Without special consideration and considerable development effort, the design systems team is blind to the usage statistics and performance metrics directly associated with the system. To gain insight into design systems, teams must manually track which components each product team uses, and then try to glean usability information from product team UX research and performance metrics.

At Airbnb, we see data from the large proportion of our native apps, which now use design system components. Connecting these stats to user metrics lets us know which components might be underperforming and deserve special attention.

Similar metrics also have an internal benefit. Dashboards containing usage data aid the internal perception of the system among product designers and engineers alike. It’s easy to imagine that tracking the use of a design system can go beyond recording end-user impressions (views) and interactions. Even analyzing the usage of documentation, design files, and other internal tools can lead to insights that better enable product teams.

But why should such insights be limited to just a few companies with the resources to create similar tooling? A module could be built for just this purpose. It would track where canon components are used in product and then apply a flag to that component. These flagged components could be polled, and usage stats could come straight back to the design systems team. The insights would then be used to improve internal tools and the system itself.

Layout aware

Another promising direction would be for our components to become somewhat layout aware, and then declare their intended use to both the system at large as well as sibling components. Given this new super power, design system components could now communicate where they should generally be used and then share information about what types of data they generally contain. Even a simplified implementation of this functionality would help designers instantly swap abstracted data sets to, for instance, see how translation might affect the layout of a particular component given a longer language like German or a right-to-left language like Arabic.

This awareness might even go a step further with a given component stating the kinds of screens or interactions preceded by its own display, and again which kinds of interactions or screens should follow upon user interaction. This awareness would enable predictive assembly.

Predictive assembly—a pattern tool

Because each component now sends messages about where it’s typically used and what type of data it usually contains, we should also be able to see existing components predictively assembled into screens. A future tool might allow the product designer to view a particular component, click a randomize button, and see the component in situ with other components arranged in an order that more or less semantically makes sense.

By allowing designers to up-vote particularly useful component groupings (or patterns), a layout aware tool featuring predictive assembly—perhaps better described as a design system pattern tool—could become an instrumental way in which product designers quickly discover repeatable patterns in the system. With just a single click, a designer would be able to compose an effective solution made of many components and export the basic design for any project. Moreover, with the advent of standardization, design systems could become plug-and-play with compositions composed by predictive assembly, allowing for a quick way to assess the integrity of a given design system.

Predictive assembly would enable the product manager, developer, or product designer to provide a set of data and ask for a menu of pre-assembled screens that display the data. We could then choose the best option, only correcting the layout if needed.

It’s worth noting that if we get particularly good at predictive assembly and consult the right minds to take it further, we will soon find ourselves in a world where machine learning provides artificial intelligence for plug-and-play design systems. Among many other things, we might witness the birth of a world where phone users could eliminate branded apps, preferring a locally installed design system that could spin up UI without needing to load templates over the network.

As designers, we continue to rely on intuition, performance metrics, and user research to create products. If a large percentage of our users can complete a task and proceed to the next stage in the flow, then we generally call the design successful. We use templating languages to add options to a design so even more users reach their goals. But by connecting design systems to artificial intelligence, we could achieve a step change in customizable UI. Instead of designing products that work for most users, systems design and AI will apply specific solutions for specific individuals.

Designers should prepare now by discovering a bit about machine learning, reading about the breakthroughs enabling AI today, and finally, thinking about how ML could impact design tools.


As digital product designers, we’re asked to ride the waves of change in our industry. People just like us helped small development teams create apps for desktop computing in the 1980s. In the late 1990s, other designers formed a coalition that pressured large software companies to unite front-end web development through the web standards project. In the mid-2000s, we focused on communication and user-generated content while developing patterns for creating web apps, and just a little later, all our work was available in mobile form factors like the iPhone. Now, after nearly 4 decades of designed computing, design systems and AI are shaking hands—presenting us with new opportunities for innovation at scale.

Every designer will now be asked how they might change custom, one-off design solutions into reusable components that grow the system. We’ll have to think more holistically, and work collectively to develop and learn a new set of tools.

How can we work together to improve our workflows and better scale design? What should be in a design system standard, and what kinds of tools could be built if such a standard existed? How will design systems and AI combine to create extremely customized interactions for end users? There are many questions, and each answer points to a possible future. What I love about design is that it enables each of us to explore the ideas we feel may have the biggest impact, and project our ideas outward and into the future. Innovation is certain.

About the Authors

Marco Suarez
Product Designer, InVision
Katie Sylor-Miller
Staff Software Engineer, Etsy
Roy Stanfield
Design Lead, Airbnb
Diana Mounter
Design Systems Manager, GitHub
Jina Anne
Design Systems Pioneer, Independent
Design Systems Handbook
Design Systems Handbook