Bliss — Creating a multi-layered design system for two sibling brands
When I joined 7Mind in mid-2022, I inherited an outdated app and a messy design system. Later that year, before I could even move forward with many improvements, we decided to start rebuilding our app and launch a new one. I and my team members knew we needed a very special design system.
We wanted to build a real system, with live docs and code parity, not just a Figma UI library. But how could we build a system that would serve two sibling brands, both on mobile + web, while having light + dark modes?
This is a very straightforward article, in which I’m going to share with you how we navigated through a long list of requirements, as well as lessons learned and insights gained at each step, for the most cutting-edge design system build I’ve ever been involved with.
Early Goals & Requirements
Low Maintenance & Fast Start — Our daily Figma workflow also had to be super fast. We wanted our libraries to be easy to maintain, with any designer being able to perform basic tasks without having to ask for permission.
Multi-brand — We needed a multi-brand and multi-device system. It should be easy to switch brand themes and equally easy to work for both the web and the mobile apps.
Documentation — It should be easy for anyone new to the team to understand the building rules for each interface, preferably by simply checking one central compilation of rules and tips.
Code design parity — We wanted to ensure that the developed components looked like the designs but also that we used similar naming conventions for components, parameters, and so on.
Automated code generation — This was an extra but we thought it would be cool if some of the code related to token variables was generated automatically, saving developers valuable time in hand-coding color codes.
Full ownership of token changes — The automated code generation setup should also allow for full design control over how tokens are used in the app. Developers would call style variables from the generated code, which meant designers would have full control over certain aspects of the app’s aesthetics, right from the comfort of Figma.
1/4 — We started by setting things up in Figma
Our first challenge was figuring out how to set up our day-to-day work in Figma. At the time we knew more or less which components we would be placing in a library and that some of these would work cross-brands and cross-platforms, such as buttons. So the challenge of how to serve these properly was top of mind.
For each brand, we wanted the system to serve both an app and a website. So, inspired by the work of the Spotify team and these two great articles, we decided to go with a layered approach, in which we created 3 layers.
- Foundations layer — one central library that keeps all the shared elements across the entire system, devices, and brands. For example, buttons are so ubiquitous that they were included in the foundations.
- Device layer — two libraries (app + web), each with specific components. For example, app-specific components such as nav bars, only exist in the app library.
- Brand layer — our design tokens, applied as a theme on top of all the components via a Figma plugin (Tokens Studio). The main difference between our brands is the colors, so we established that we would store theming information at a token level.
This setup covered our needs and felt very flexible, but the tool conventions also felt a bit imposing. So, defining which to adopt or ignore took us a while.
Lessons & Insights
- We messed up on the last layer — When building in layers, you are essentially creating multipliers for possibilities and problems and our multi-theme approach didn’t work so well. We were still learning the (sometimes conflicting) conventions of our tools (eg. Tokens Studio VS Supernova), not even sure if these were the right ones! So taking the time before settling on a set of ground rules is important.
- No need for duplicate components — When we started, we thought we had to design light + dark variants side-by-side. Eventually, we realized having components for each mode wasn’t necessary after introducing a proper multi-theme token structure. Tokens are responsible for theme-switching (Figma variables seem to do it even better), and all that is needed is to pick a default theme when designing.
- Including helper components in our foundations library was a great decision — We included Figma cover, screen-group titles, grid helpers, and a few more. As we built new tools, we maintained them in that library, so they would always be consistent across projects.
Impact
- Having this structure saved us a bunch of time. Each designer was able to pursue separate lines of exploration and submit improvements to the design system unquestionably.
- We ended up using Figma variables for the color styles, which allowed us to conveniently switch themes at a page or frame level. We merely had to flip a switch once we started building the second app by reusing lots of screens and components.
- Ultimately, having things set up in this centralized way translated to visual consistency across platforms and brands.
2/4 — We had to learn how to structure design tokens
Our apps were going to be aesthetically very similar. Typography, spacing, and most tokens would be the same, the main difference being colors.
Component-wise, we had been building with atomic design in mind. All our Figma components were already broken down into atoms, molecules, and organisms, so we were used to it. We just hadn’t been able to consider design tokens beyond Figma styles and this time we wanted more control and flexibility.
A big part of the community seemed to be on board with Tokens Studio. After a few tests with other tools, that was enough for us to decide in its favor and focus our efforts on exploring the ideal token structure. It took us a while, though.
Like the design system itself, Tokens were also built in layers:
- Foundations — most of our tokens exist in 3 sets: colors, typography, and dimensions. Except for colors, most of these are applied directly in our designs. Colors rather function as source palettes to feed the following layers.
- Brands+Modes — our themes are just a set of colors based on a combination of brand colors and arranged by mode. Brands act as a 2nd layer by offering a sub-set of branded colors. The final layer is semantically named and serves the final styles in our Figma variables.
These tokens are all managed locally through Tokens Studio and pushed to a GitHub repository, our source of truth in JSON format.
Lessons & Insights
- Not everyone interprets atoms, molecules, and organisms similarly — While trying to establish a collaboration with our developers we agreed atoms were the smallest indivisible element (eg. a color) and molecules were then a combination of two or more atoms (eg. a button). Still, we realized this conversation has a few rabbit holes.
- Developers might not understand why you kept so many colors in your scales — You can try to explain that scales aren’t to be used as-is but they’re a pre-defined, broad palette from which your team can pick darker/lighter versions of existing colors. In the end, you might not even need the scales in code format.
- Dimension tokens felt like extra work — We still apply values from the tokens list but we do it by hand since it’s a lot easier to try out which ones work best.
Impact
- While the whole thing was a learning process for everyone involved, discussing token names and their structure as common ground helped us establish the guardrails of our design.
- The handover for the first app we built around this design system was very easy since we had only a few styles. Now that themes have grown and we have more tokens (we made them more semantically accurate so the list grew), I believe it’s still quite beneficial to have said common ground.
3/4 — Automating the handover process was cool
In my opinion, a design system is nothing if it doesn’t materialize itself into something else. In our case, the goal was to have parity with code, so developers and designers could speak the same language when we referred to a component by name. Knowing with full confidence it looked the same in Figma and rendered code.
Since design tokens are stored in JSON format, we knew it shouldn’t be too hard to convert them into Dart code variables and make all our styles ready to use by our devs in Flutter.
This would also serve another of our goals: to have a setup in which we would control the styles rendered in the apps by directly pushing changes from Figma. Ultimately we would be in semi-direct control of the look of the rendered app.
The setup we ended up with can be broken down as follows:
- We create and manipulate tokens in Figma via the Tokens Studio plugin.
- Through the plugin, we push/pull data to/from a dedicated repo in GitHub, which acts as our source of truth.
- With each push, our CI actions are triggered, pushing data into Supernova via the command line.
- Upon receiving new data, Supernova generates new Dart code and pushes a PR to the final Flutter repo.
Although this setup took us some time to perfect by working around each tool’s conventions, currently it’s working pretty well.
Lessons & Insights
- Are we using these tools right? — Since we started working like this, new tools and different connectors have been launched, so we could set this up in a handful of different ways using these same tools. But for now, we feel that each tool serves its purpose, so we’re happy to continue to support this somewhat complex toolset.
- Token names and namespaces are hard to control — Actually, they’re not hard to control but it’s hard to find one convention that fits well in all of these systems (probably due to the complexity described in the previous point). We tried keeping our namespacing simple and descriptive but still ended up with Dart variables that are a bit too verbose and no way to control this along the way.
Impact
- We still haven’t pushed changes from tokens directly to production but we’re eager to try it since we’ve already identified a few tweaks.
4/4 — Documentation can be a beast on its own
From the start we wanted documentation to be a central part of our design system. This was more than a UI library, more than a modular code repo. It needed to be the go-to-place for new team members to read about how we build and maintain apps at the company.
Knowing how to combine all of these components, rules, and tokens was the magic ingredient that brought it all together as a system.
Currently, most documentation started being written in Figma, since it was the most mature representation of the design system. We even considered saving some of this documentation in Github via the Gist plugin or Figma’s native documentation features. However, these still wouldn’t provide a central and agnostic platform anyone could check.
We’re now considering moving all the knowledge into Supernova as soon as we manage to connect all the dots, including figuring out how to best represent (render) our Flutter components on a Supernova documentation page.
Lessons & Insights
- It’s hard to know where to stop — How detailed should you get? What is the line between relevant details and obvious ones? With Figma’s Dev Mode, there are a lot of specs that consumers of the design system can figure out themselves or find documented in Figma. In this regard, we mostly tried to describe behaviors and limitations for our components which are much more subjective than measurements and color codes.
- Writing and explaining are only part of the work — Formatting and putting all the information in its final format and platform is a whole different topic. Structuring Supernova-like pages takes time and hard to pick a template that works for every scenario.
- Who’s going to maintain this? — The obvious problem of every company without a dedicated team to maintain design systems. We had this in the back of our minds when we standardized documentation in Figma but keeping things up-to-date while doing day-to-day work might be a tough challenge.
Impact
- While we still haven’t grown our documentation to the extent we would like, we believe writing it down while things are fresh will certainly have an impact as new people join the team. Everyone involved has a good understanding of how things work but it won’t hurt if we write down the things that (for now) seem obvious.
Final words
In wrapping up our journey, I must say it’s been quite the adventure! From diving into the depths of token best practices to learning the ropes of automation tools, we’ve tackled challenges head-on and come out wiser.
Even though our early goals were clear, we hit a few bumps along the way, like figuring out the best tool conventions and making them work together. But these hiccups taught us valuable lessons, like the importance of clear and simple token naming.
Overall, this project has already started saving us time, it fostered collaboration and brought visual consistency to our projects. As we continue to launch new apps, we will certainly keep refining the design system, super excited for the work that lies ahead!
👋 If you would like to ask me anything about design systems or related topics, feel free to reach out via LinkedIn. ✉️