Capiche Design system (CDS) is a living collection of guidelines, constraints and components that can be assembled to ideate, design and build digital products at Capiche.io. The system serves to streamline product development by simplifying collaboration and setting clear design and build standards for interface design. This is the story how I led the creation of CDS, the design decisions that want into building it and the rules set for maintaining it.
When I joined Capiche, the application UI was a slightly modified variation of an imported bootstrap stylesheet. Other than stye adjustments and color constants, not much was happening in the way of interface standardization. With no dedicated designer on the team, focus was less on interface considerations and more towards validating market fit and core competencies with customers.
In time, our product roadmap demanded functionality beyond our core offering, and practical pathways for agile feature builds started to be paved. After months of iterative sprints - it became clear that our design/dev ops workflow was suffering from lack of shared implementation models. With the team’s blessings and amazing support, I rolled up my sleeves and got started.
All interfaces evolve systems, even if that evolution is not intentional or carefully considered for reusability/scalability. If an interface exists, then the first step towards standardization is to conduct an audit of existing elements. Over the week, I explored our use of typography, colors, affordances, UI controls, components across a variety of states. I then identified and documented patterns, similarities, and inconsistencies across a variety of breakpoints and devices.
At the time, I also worked closely with engineering to examine front-end markup to discern whether inconsistencies were also prevalent in how the stylesheets were written. It turns out that the stylesheets were also accumulating inconsistencies in applied styling. This audit helped us come to terms with the cross-functional hygiene that needed to take place. After balancing our time and constraints, we aligned on the scope and got started in parallel.
When you work eight-plus hours on a design tool, every second counts and every lag hurts (I’m looking at you Sketch). Speed is one the main reasons I stand by Figma as my tool of choice for interface design. Besides its brilliant response rate, the tool’s multiplayer design mode, shared styles, dev inspect, version control and the smart component system make it a powerhouse for interface design and specifically design systems. The introduction of variants is a game changer, I was able to migrate over 60 components from our library in less than a day. The logic of setting properties and toggling between them enabled me to flesh out states that I’ve opted against in prior builds. When browsing the asset panel tree - variants result in less entries and searching for the right control is way easier than before.
Instead of manually selecting values form a limitless pool anytime a design decision needed to be made, having constrained value selections drastically simplifies design and build. Systemizing values for colors, type and spacing alleviates decision fatigue and ensures consistency in all use-cases. Setting constraints also spares us form having to perfect our value decisions early on in the process. Defined variables enable decisions to centrally controlled, to be amended and cascaded at any time. Even though value choice was not that important, the structure that informed their creation - definitely was.
I avoided using palette generators when choosing my primary colors, to avoid outputting shades that differ numerically but look practically the same in production. I attempted to bring balance by using the 60% - 30% - 10% rule - the largest portion should go to the dominant primary colors, the third of the composition for the greys, and 10% goes to the selections that make up the accents. Since our users experience a considerable degree of cognitive load when using our applications - we opted for colors that will get out of the user’s way to maximize information scanning and processing.
The primary set colors will be used for primary actions, navigation, and other weighty interface elements. The grey selections will be applied to texts, panels, borders, boxes, shadows and form controls. This set will be used to communicate information clearly, outline space, and inform borders and element spacing. For accent selections, I choose three different sets to help with communicating state and feedback affordances.
Initially, I selected Apple’s SF pro as the main interface font due to its battle-tested reliability for application design. After realizing its limited licence for commercial use, I set out to search for fonts that offered a similar proportion between lowercase and capital letters (x-height). I landed on Inter, a font designed by Rasmus Anderson. Inter has a relative x-height of 3/4th the cap height and reads very well on smaller screen sizes.
Next, I set out to create a typographic sizing system. From experience, I’ve found that the jumps that come from modular scales vastly limit the pool of font sizes. So I used my own judgement for setting incremental values and used semantic naming conventions to make it more intuitive to apply text styles during design. As beautiful as mathematically precise formulas can be for size setting, when it comes down to actually designing our UI - modular systems don’t always offer the best sizes. I also referenced Inter’s dynamic metrics calculator to get guidelines on line-height rendering for optimal readability.
We’ve all tried trialing arbitrary spacing values when prototyping, it seems so much easier to just randomly space elements based on intuition alone. Eyeballing values for every spacing decision space is tiring, inefficient and error-prone. This approach makes it impossible to achieve consistent spacing and will cause a lot of frustration when production files are inspected by the engineers. For a spacing system to be useful, the relative differences between adjacent elements must be taken into consideration to ensure visual harmony and layout consistency. First, I needed to define the base increment value, then allocate a scale using multiples of that choice - I used 16px as my reference base for both horizontal and vertical scales.
The earlier interface audit exposed the lack of consistency prevalent in production UI. These outputted interface elements that were not only stylistically different, but also resulted in patterns that did not perform well across different breakpoints and screen sizes. None of this was intentional or a result of malpractice - the team’s energy was simply focused on other problems that needed to be solved given the resource constraints. To scale effectively and prevent avoidable interface asymmetries - we needed change to happen at foundational level and not by policy additions or individual outliers. Standardization should not depend on any one designer, a clever developer or an enthusiastic new hire - it needed to be baked in from the get-go.
The underlying design methodology that underpins CDS is Atomic Design by Brad frost. Atomic design is a mental model for thinking about how building blocks are created and assembled based on an explicit order and heirachy. The approach involves crafting small indivisible units that can be assembled together to form more complex permutations. Atoms, the smallest units can be created and then combined to create more complex molecules. These molecules then combine to form larger organisms that are then assembled to generate templates and then data-ready pages.
Components are organized in the CDS library by how they are named at various levels of heirachy in the Figma file. The default structure set and maintained for consistency is File/Page/Frame/Layer. Using this system makes it easy to find components in the assets panel, swap related components, and improve designer experience for other team members. The benefits of structure will become even more apparent when archiving projects that end up being parked due to prioritization. Diving back into a well organized file after being away from 6 months drives this point home for me every single time it happens.
Naming conventions are important on the component level as well. Figma programmatically assigns relationships between components based on patterns in naming set by the designer. The addition of variant functionality makes managing components a breeze by combining all instances into a transformer-style master component. Naming patterns also allow designers to seamlessly convert component variations into standalone variants in one click given correct onset naming. Asset panel bloat is vastly reduced and simplified and toggling between variations is delegated to the right sidebar instead.
Combining Atomic design methodology with Figma’s powerful styling and component system allows us to achieve a seperation of concerns for practical modularity. Vast improvements in speed and efficiency enables quicker ideation, cascading iterations and more reliable production pipelines. For example, if we later conduct an accessibility audit and find that our blue needs to be changed for readability - we only have to amend the variable once and see the change apply to all instances across many different design files. The value of such efficiency speaks for itself when experienced under the pressure of production sprints and clear deadlines.
After several months, CDS started to take shape and it became time to start anticipating how the system will be maintained when more designers join the team in the near future. Inevitably, new patterns and components will be required to address problems that will emerge from tackling sprint requirements. Pattern libraries will need to be amended to meet accessibility findings, global design decisions and functionality constraints.
After CDS started to take shape, a crucial consideration became how the system was going to be used by others and how it was going to be maintained. As the system is used for production, new patterns and components will surface to address problems that emerge from tackling sprint requirements. Pattern libraries will inevitably need to be modified for feature additions, code refactoring, accessibility and cyclical design tweaks. Its important to be discerning about adding new UI patterns to CDS, if every design session results in a committed pattern - CDS’s will quickly and inevitable become bloated and difficult to navigate. That’s why active users of the system should take time to evaluate whether their design can be achieved by modifying existing blocks rather than creating entirely new ones. We used Canonical's open source vanilla pattern flow created by the brilliant Inayaili de León as our guide for component design making.
The end goal of this system is to enable a reality where CDS and Capiche applications are perfectly synchronized. Committing changes to a any pattern the library should not only reflect everywhere the pattern is used in the design environment, but the change should make its way to every instance in production as well. We have a long way to go before this becomes our reality, but we don’t have to wait till then to benefit from standardization. CDS has already made an positive impact in ideation, dev-design ops and feature validation workflows.
After establishing a single source-of-truth and a home for evolving pattern libraries, the next step involves documenting CDS to help communicate constraints, guidelines and vetted design decisions to simplify on-boarding and ensuring alignment across cross-functional teams. Doing so will allow us to scale our applications without compromising on confirmed standards for performance and reliability. In parallel, I have started working with engineering to build our pattern library via Storybook (a case-study coming soon in the next coming months).
Thanks for reading, if you feel like reaching out with thoughts or just feel like discussing all things design systems - drop me a line at firstname.lastname@example.org