Managing Technology-Agnostic Design Systems

Users don’t care that one UI is built by Team A and another is built by Team B. Users don’t care if for one project the team followed a scrum process, while another project followed a kanban process. Users don’t care if React is powering this feature while Angular is powering another. Users don’t care that one page was served up by WordPress, and another page was served up by Drupal. A UI is a UI.

Easily one of the biggest benefits of establishing a design system is the ability to produce consistent UIs across teams and products, irrespective of the technology stacks those products stand on. However, that’s easier said than done.

I do design system consulting with large companies, and I find nascent design systems teams fall into a trap of coupling a UI with a specific tech stack. Creating a technology dependency in order to achieve a specific UI style inherently limits where that UI can go.  That might not be an issue if your design system only serves one or two applications that share the same technology stack, but this becomes a big issue for organizations that manage tons of applications built on a smorgasbord of technology. Those are the same organizations that can reap the most benefits from a solid design system.

So how can we set up design systems that are portable and attainable to any tech stack while simultaneously helping product teams efficiently create consistent UIs?

Tech-agnostic design systems & tech-specific flavors

In order to create a portable UI, a design system should be technology-agnostic. A web frontend is created with HTML, CSS, and DOM-specific JavaScript, which means that’s about as far as a canonical tech-agnostic design system can go.

Of course there’s a lot of work that goes into getting that HTML, CSS, and presentational JavaScript onto a page. That’s why teams reach for different backend languages, templating languages, and JavaScript frameworks. Which is where things get complicated. The evolution of JavaScript has especially made things thorny. since it’s gone from simple UI manipulation (a la jQuery) to full-fledged application frameworks (a la React, Angular, Ember, et al). It can be tough to find to find the seams of where the canonical design system ends and where the tech-specific version begins.

That’s why with my clients I’ve been recommending architecting a tiered system that allows organizations to maintain a canonical, tech-agnostic design system in addition to tech-specific flavors of that design system. The end result looks something like this:

Design system workflow from tech-agnostic to application-specific

The tech-agnostic version of the design system includes HTML, CSS, and maybe some light presentational JS (i.e. toggling classes for a dropdown or accordion, but nothing more than that).

The tech-specific versions of the design system eat the canonical design system as a dependency, and transform things into a way that fits with the tech stack. For React, that means transforming components into JSX. For Angular, that means transforming components into directives. For Drupal that means transforming components to work with the Twig templating engine. The idea is to take the agnostic UI and convert it into a form where applications running specific technology can easily make use of.

Each application then eats the appropriate tech-specific version of the design system as a dependency. Product teams can do their jobs wiring up business logic and pouring content patterns into the display patterns provided by the system.

This architecture provides a clear path for getting the tech-agnostic, canonical design system into real working software that uses specific technologies. Because it doesn’t bet the farm on any one technology, the system is able to adapt to inevitable changes to tools, technologies, and trends (hence the placeholder for the “new hotness”). Moreover, product teams that share a tech stack can share efforts in maintaining the tech-specific version of the design system.

This is a process

Now, it’s not feasible for a centralized design system team to actively create and manage all the tech-specific flavors of the system, but it’s critical for the team to help define the process by which tech-specific flavors are created and maintained. With a solid strategy in place, product teams know their role and responsibility in the creation and maintenance of the design system.

Bootstrap is a good example of this model in action. There is a tech-agnostic version of Bootstrap that provides a set of components and styles. But then there are also React, Angular, WordPress, Drupal, etc, flavors of Bootstrap that take the core HTML and CSS and convert them into tech-specific implementations. Individual applications can eat those tech-specific versions of Bootstrap as a dependency. When the canonical Bootstrap ultimately updates to version 4, those tech-specific flavors will roll those changes to their tech-specific implementations. From there, applications using those tech-specific flavors as a dependency can update and receive the version 4 Bootstrap UI.

There’s a lot more that goes into this process, and there’s an opportunity for this to very much be a two-way street. I’m excited to talk about that in another post!