Towards a universal Design System

Tim Petricola
Alan Product and Technical Blog
6 min readMar 12, 2024
Photo by UX Store on Unsplash

At Alan, we build a diverse range of products on web and mobile platforms. All our products need a cohesive identity and user experience to provide the best experience to our users.

In 2023, we started a journey to reshape our Design System’s implementation in order to improve quality while increasing engineering velocity. This is the story of how our Design System became “universal”.

The Genesis

The original pull request kicking off our Design System, back in 2019

Alan’s Design System, “Murray”, began its journey as a simple means to share a Button component between two web products.

Fun fact: Alan’s mascot being a groundhog, we decided to call our Design System “Murray”, after Bill Murray, who played in Groundhog Day. That’s how easy it can be to name a product.

Originally sparked by a collaboration between a single engineer and designer, it has since flourished into a much bigger project. It now has three flavors:

  • a Figma-based design source of truth, owned by designers
  • a React-based implementation, for our web products
  • a React Native-based implementation, for our iOS and Android applications

Murray’s primary aim is to ensure a consistent user experience across Alan’s products, fostering a familiar environment for users while effectively conveying the brand. However, maintaining consistency across the three versions of the design system presents challenges, including the potential for discrepancies and diverging implementations.

Another significant goal of Murray is to enhance efficiency within the team. By designing components that can be reused across different platforms, the system aims to streamline the development process. Again, the existence of three distinct flavors of the Design System complicates this objective, as new design components need to be implemented multiple times, and changes must be replicated across all versions, making the process both time-consuming and prone to errors.

The switch

In 2023, we decided to give some extra care to our Design System, aiming to tackle these challenges. With our team having grown to include around 100 engineers and designers, we saw a prime opportunity to not only speed up our processes but also to enhance the quality of our product for our end-users.

For years, we’ve been relying on React for web development and React Native for mobile applications. We’ve always shared some code between the platforms (API calls, React hooks, …). This led to an exciting initiative of also harmonizing UI and its implementation across.

Introducing React Native for Web…

The web and mobile platforms offer distinct development environments, with the web relying on HTML, DOM, and CSS standards, while mobile development, specifically with React Native, uses its own set of primitives and styles.

// 🕸️ Web
<section>
<h1 className="title">Hello</h1>
</section>
// 📱 Mobile
<View>
<Text style={{ fontWeight: "bold" }} >Hello</Text>
</View>

React Native for Web bridges this gap, allowing developers to write code once and deploy it across both web and mobile platforms.

// 🎉 Web & Mobile
<View>
<Text style={{ fontWeight: "bold" }} >Hello</Text>
</View>

This unified API simplifies development, offering a seamless experience across platforms without compromising on the quality or performance of the applications. It is also very mature and used in production at both Twitter and Meta.

In short, it allows to build a “universal” implementation, targeting several platforms (web, iOS, and Android).

… and Tamagui

Once we’ve picked the low-level abstraction layer to have a single implementation working across web and mobile platforms, we embarked on building our Design System primitives. We saw two paths. We could either craft everything from the ground up, or leverage an existing library such as NativeBase, Dripsy, GlueStack (still in alpha at the time) among others.

After a thorough evaluation of available options, we picked Tamagui for its compelling advantages. Tamagui stood out for its straightforward approach to managing design tokens, its code optimization for both mobile and web platforms, and its extensive library of headless components.

Tamagui’s adaptability makes it an excellent choice for our needs, allowing us to focus on delivering high-quality, consistent user experiences across all platforms.

The paradigm change

Embracing a universal approach to development introduces its own set of challenges. Transitioning to a universal framework, specifically “React Native for Web,” necessitates adopting mobile-first paradigms, which marks a significant shift from traditional web development practices. This shift entails:

  • moving away from cascading styles to a more structured approach
  • utilizing only flexbox for layout management, foregoing other CSS layout methods
  • saying goodbye to the nuanced capabilities of CSS pseudo-states and nesting.

Despite these changes, platform-specific adjustments remain feasible, allowing for tailored experiences where necessary, such as leveraging web-only APIs or differing UX patterns on mobile. This adaptability ensures that while the default approach may have shifted, the flexibility to meet unique platform requirements is preserved.

It’s dangerous to go alone!

Document, document, document…

Murray documentation for a component
Murray documentation for a given component

We’ve built a comprehensive documentation website using Docusaurus, offering a rich set of features:

  • detailed documentation of every component
  • various interactive playgrounds that allows for hands-on experimentation with component
  • plenty of examples to showcase various use cases
  • health metrics dashboard: providing insights into component usage, identifying non-universal components, and more
  • in-depth guides designed for both designers and engineers, facilitating a better understanding and implementation of our system
Documentation’s components health page

Close the gap

Custom Figma plugin

To bridge the gap between design and development, we’ve created a Figma plugin that effortlessly translates Figma components into code, complete with a live preview. This tool can significantly streamline the process for engineers, reducing it to simple copy-pasting tasks.

It enables a seamless workflow between designers working in Figma and engineers in their code editors, ensuring consistency and efficiency in bringing designs to life.

As Figma started charging more for their Dev plugin, we’ve put this custom plugin on hold for the time being.

Exhaustive stories

Single story, loaded in both web and mobile Storybook

In order to test the hundred variants of each component, we saw it important to work on an exhaustive Storybook. Having a universal implementation of each component allowed us to load our stories both on web and mobile, to better ensure look and behavior consistency across platforms.

Visual regressions

Pull Request comment for visual regression
Comparing the before/after version of a visual change

To safeguard the integrity of our design system and prevent disruptions, we’ve implemented visual regression testing for any changes that might affect our design system’s code. We’re using Reg Viz, a tool that automates the detection of visual discrepancies in Pull Requests. This proactive measure ensures our design system remains consistent and functional, minimizing the risk of breaking changes

Looking ahead

While it’s only the beginning, we see more teams beginning to create universal features atop this system, indicating a promising trend towards enhancing engineering velocity. There is a long and bright road ahead building a universal product!

The ecosystem is also evolving rapidly. The recent react-strict-dom, essentially a “React DOM for Native” (in contrast to “React Native for Web”), is already deployed in Meta’s products, we’re closely monitoring its development for potential adoption.

--

--