At Smartly, we invest heavily in product design, discovery, and user research. As we shared in our previous blog post, we had been building a design system to ensure the look and feel of the product stayed consistent across different areas and platforms.
The next step was adapting this new design system across our entire platform. Oh boy, were we in for a ride!
The biggest challenge in this transformation was the sheer size of our application. To address this, we created a specialized team called FlexForce, composed of “self-certified expert front-end developers 🦸♂️.” This team allowed for collaborative learning, code reviews, and joint planning, which significantly sped up our delivery process. We firmly believe investing in a cross-collaborative project like this would largely benefit any tech organization.
Besides forming a new task force, we also leveraged codemods, which cut our delivery time almost in half, making the migration much more efficient.
Look at these codemods-powered hockey stick DS adoptions by each project!
In the past, time constraints sometimes led us to implement custom designs instead of adhering to the design system, resulting in inconsistencies across the platform. This migration was the perfect opportunity to set things right.
We transitioned from styled-components to TailwindCSS, removing excessive customizations and embracing the new Tailwind features.
Yes, that’s right—codemods didn’t always save us. Aligning our user interface (UI) platforms felt like gathering all the six Infinity Stones. But we managed to succeed, and sorting them out is now a smoother process.
When we decided to migrate to a new design system that was still in development, our team was skeptical at first. The system initially only exposed primitive components, however, to our advantage, this allowed us to actively provide feedback and improve the components in real time.
We believed that by focusing on these foundational elements, we could create a more streamlined set of components that was easier to maintain and customize. This helped keep our design system team small while focusing on other deliverables.
Our users also started noticing these changes early on, reinforcing the continuous evolution of our app.
Looking back now, our product has certainly been evolving. However, it came at the cost of revisiting the same UI component multiple times as new design system components became available. In addition to this, we had to fix tests over and over again, which only got better with time.
When we began our design system migration, our team was at a crossroads, divided between two strategies.
The first approach was to migrate individual components across the entire application. Wherever a user encountered a specific component—for example, a dropdown—they would consistently see the new, updated design. This method promised uniformity across the app, ensuring that users wouldn’t experience any visual dissonance as they navigated from one section to another.
The second approach took a different route. By focusing on one specific part of the application and updating all components within that view, users would be greeted with a completely refreshed experience in that area, even if other parts of the app still used the old design system. This could create a more impactful and noticeable change, making it clear to users that we were actively evolving and improving the product.
In practice, we ended up adopting both strategies at different stages of the migration. Initially, we started with the component-by-component approach. At that time, only a few components were available in the new design system, so it made sense to roll them out wherever they appeared. This ensured that users would begin to see the new system's benefits in the most frequently used UI elements, even if broader visual consistency wasn’t fully achieved yet.
As the design system matured and more components became available, we shifted gears to the view-by-view strategy. By this point, we could fully refresh entire sections of the application, offering users a cohesive and modernized experience within those specific views.
Each update had to be manageable, revertible, meaningful, and complete.
Our initial goal was to deliver a fresh, modern look and feel for our application. That simple goal translated to even greater benefits:
We can’t wait to share more product development success stories in the near future as well!
We are actively looking for new team members to help build out our vision. Check out our open positions!