There’s a problem with the way we think about design systems. On the one hand, they help designers and developers collaborate more efficiently and avoid unnecessary work. On the other hand, they’re products unto themselves. They require thought, maintenance, and work, and they’re never truly done.
In the world of government technology, this can be magnified exponentially. Most agencies have a complex array of programs and services with vastly different needs, users, and interfaces. In contrast, even a large business in the private sector may only need a design system for one main use case or user persona.
As more offices in an agency adopt a design system, we start to see programs with drastically different use cases consuming the same design system. At first, this might not be a problem. It’s a good thing to have an entire organization using the same color scheme, fonts, and UI patterns. But as an agency builds its design system, they lock in more and more decisions. If the design system has a component library written in React, but another program has a legacy codebase in Django, you’re left with the challenge of either rewriting the legacy codebase in React or porting the components to Python (or some hybrid implementation).
Various programs might also be addressing completely different groups of users. An API documentation site would target developers while a healthcare program might target adults looking for a wide variety of coverage options. The needs of these two user groups can be fundamentally different. Anything from a banner template to a hamburger icon might be more or less usable depending on the user. And once again, the maintainers of the design system and the program teams are left with the fundamental question: how do we most effectively strive for consistency across our organization without making our applications and websites less useable for the people who rely on them?
Again, there are many paths forward, some are subtle and others are bold. For right now, let’s examine two directions: incorporate everything into the design system, or make the design system as small and flexible as possible.
Option 1: Incorporate everything into the design system
Digital products tend to grow larger and more complex. You build something that solves a problem, then you realize that it needs to do more, so you add features. This doesn’t necessarily raise red flags.
If your strategy is to continuously add features, components, or patterns as needed, you’ll likely end up with a robust system that can do a lot of things well. And perhaps more importantly, your organization will remain close to having a single source of truth for your programs or groups.
But there is a cost associated with this growth. As a design system becomes more complex, there are more potential points of failure. And since the future is never certain, there is a risk that a needed feature will directly conflict with a previous decision. At that point, any change can become far more complex because the design system itself has become complex. The single source of truth necessitates all those who adopt the system “bend the knee,” so to speak.
As a designer and developer building and consuming these systems, I have felt the benefits of a robust system. It has allowed me to go from an idea to having a working site incredibly quickly. It frees me from having to make a thousand minute decisions about line height or grid layouts. If I need a button — I have a button! But I’ve also had to weigh these benefits against the burdens these robust systems can place on projects. I’ve experienced updates with breaking changes that require a tremendous amount of time and effort to address. I’ve needed specific components or slightly different styles and had to Frankenstein together an amalgamation of custom CSS and design system CSS.
And more often than not, I’ve been left wondering about a slightly more nuanced path. A path around the growth of a design system that can still alleviate common pain points or reduce decisions without being so rigid in implementation.
Option 2: Make the design system as small and flexible as possible
Under this methodology, the design system would be the smallest single source of truth possible. On top of this minimal design system should be a highly-defined strategy for governance, collaboration, splintering, and growth.
As your agency adopts this minimal design system, the burden of addition and contribution is passed to the individual teams that are consuming it. But that burden comes with the freedom to build in more languages and with fewer constraints. Practically, this model looks a lot like a library of packages where consumers are only taking the parts they need.
I should note that this pathway assumes that you’re building a design system from scratch, which is often not the case. If there is already a robust design system and you’re starting to experience some of the burdens of that growth, I believe you can use this model to improve the flexibility of a system, even if it can’t be immediately paired down in size.
What does that need to look like?
Whether you’re building a design system from scratch or attempting to make an existing system more maintainable, these principles and methodologies can help your team more effectively collaborate.
Start by determining the smallest possible “single source of truth.” It should be a list of principles that could apply to any project, regardless of user, purpose, or mission. For example:
- All components, pages, and content should be accessible.
- All sites should be based on this color scheme.
- All design and code conventions should follow a defined structure.
- All content should have a consistent voice.
- All contributions to the design system should be part of a clearly defined process.
- All components of the design system should be as technologically agnostic as possible.
- All maintenance of the design system should follow a consistent cadence.
- All communication with the core design system team is easy to discover and maintain.
Use the specific needs of your agency, company, or project to guide your principles. The goal is to have them fit into a “global” design system that is agnostic to differences in programs, like language or design tools, and accommodate projects built on different stacks. They should also encourage each program to build resources that make it easier for future projects on those stacks, without forcing new projects to adhere directly to a specific technology solution.
This method requires a highly defined process for teams to follow when creating their own resources, styles, or components. Clearly state this process in the documentation for the design system and refer to it often in communication. Healthy channels of communication between programs and the design system maintainers are critical. Encourage teams (especially ones working on similar projects) to partner together in building these resources. For example, if two teams are working on a banner component, what is the highest level of consistency they can achieve? Can the component be consumable by others? What are the guidelines for altering or forking that component?
As your common resources grow, you could end up with a rich library of components, patterns, and features — but you would have avoided some of the pitfalls of an “everything or nothing” system, such as resource bloat.
At its core, this model strives to stop attempting to anticipate everything consumers might need. Instead, build the path that allows the community to build anything together.
There is no “best way” to build or consume a design system. But the reason that Ad Hoc’s Design Systems Working Group is trending towards more minimal systems and defined patterns for growth is because we’re starting to understand more clearly what makes a design system successful and healthy. More often than not, a design system fails because it becomes a burden on the consumers. The code may be out of date. The consumers might not feel like they have a voice in the system roadmap. The documentation might be unclear. Growth doesn’t kill a design system alone, but growth without clear direction will lead to an unruly and unmaintainable system. Even if it achieves the goal of visual consistency across a program, it may still be hollow and stifling. Consistency and adherence are important until it’s an impediment to progress.
To build a successful design system is, really, to build a successful community. That is why starting with the most minimal elements of global “truth” is so important. Communities and design systems need a small, clear set of core values to rally behind. And from that core, they can build a complex and functional infrastructure. This is far easier said than done — but in our work for the federal government, we’re committed to partnering with, learning from, and empowering the agencies and people we serve.