Lessons learned while moving our Frontend to a Monorepo

Unmudl and TuringTech's experience moving Unmudl's frontend to a monorepo.

I joined Unmudl as a full-time CTO in July 2021, that is when Turing Technologies inherited our dashboards/portals from an outsourced dev team. During the initial technical audit, TuringTech's lead Sarmad Kazmi was appalled to know that out of four portals, three were made in Angular and the fourth one in React. These were maintained inside three separate repositories each with different coding practices, dependencies and style. The angular portals were made on top Bootstrap Angular while the React one was made on top of Ant Design. This created a lot of confusion and a very steep learning curve among TT's team. Fixing a small bug/issue was painstakingly slow and took days to reach completion. This also created a recruitment challenge, to maintain three separate portals required at least one full-time Angular engineer, while a new team was being built to re-platform the frontend in Next.js.

In principle, there is nothing wrong with using different JS frameworks for different parts of the applications, however in case of a pre-seed funded SaaS company (as we were back then) actively fundraising, this was nothing short of a catastrophe and could've led us to premature failure, as the tech wouldn't be able to catchup with requests.

There were major design inconsistencies as well which didn't sit well with our design team, it would require our team three times the effort to do a small improvement. I'll illustrate this in detail below.

Three out of four portals divide the address from Google Places into city, state and country while displaying the complete address inside the main location field, while one was using the Google Place ID inside a single field to fetch the address every time the the request was received.

For example: when we tried to add floor number with the location, this took 2 engineers (one Angular and one React) to go through three different repositories and four portals to do the EXACT SAME THING, which in a perfect world should've been done by one engineer from inside a single folder. Hence, a solution that ensures a single source of truth became my topmost priority while considering potential solutions for re-platforming our frontend.

These design inconsistencies were present all across the project which took a toll on our engineering team.  I am truly grateful to Haseeb Tariq for initially maintaining the portals and ensuring the issues were resolved on time, and later Ureesh for using his rusty Angular knowledge from his college days to maintain the legacy portals for the past few months.

Add card module had the same issue with inconsistency, notice the module above doesn't require the name field.
Design and functional inconsistencies in the Funding Questionnaire.

We considered two options:

  1. Create a yarn/npm package for our components, styles and frontend tokens. A skilled engineer (with great design and aesthetic sense) would ensure quality and act as a gatekeeper. Based on my research, Aircall and WeWork follow this approach.

    Advantage: One highly skilled frontend engineer can maintain the package while others can build pages and portals.
    Demerit # 1: Each repo would still have different coding patterns based on how these components are structured, mutated and used. This would put us back in the same situation we were trying to get out desperately.
    Demerit # 2
    : The package would need to be maintained and published, as a startup our goal is to reduce as much roadblocks as possible to ensure agility.
    Demerit # 3
    : Code Reviews will take more time as the reviewer would need to go to each repository and pass the pull/merge request separately.
  2. Use mono-repo for our frontend, with different apps using shared resources, packages and libraries:

    Demerit: Build times for compiling code will significantly increase, and our contractor would need to invest heavily in new equipment.
    Advantage # 1
    : Single source of truth can be ensured inside a single repository.
    Advantage # 2: Small changes and design inconsistencies can be easily handled from a single repository.
    Advantage # 3
    : Any future refactoring and improvements can be done faster.
    Advantage # 4
    : A single gatekeeper can maintain code quality, consistency and structure.
    Advantage # 5
    : Our whole frontend team will be reusing the same resources, which makes it easier for us to move engineers from one portal to another in case of change in priority.

Before making a final decision, I did some research of my own and came across this excellent talk at Uber Technology Day in 2017.

Uber Technology Day: Monorepo to Multirepo and Back Again - Link

I explored products from companies which (I assumed) might've encountered the same problems as us due to different dashboards/views for different users and providers. While exploring UpWork, I noticed /nx in their URLs.

We studied directory and code structure of Shopify's Polaris, Wise's Neptune and Polarwind by Envoy. Later we designed our own structure which would be more suited to our use case.

Examples of generic structure and hierarchy for setting up a frontend monorepo, we used a similar structure in our case.
Sarmad's initial commit in December 2021.
Difference in process of migrating vs. building from scratch.
Decision tree on how to structure and architect new components/collections or generic functions.

Some of the advantages we've already noticed are:

  • Single source of truth — Instead of having a lot of repositories with their own configs, we  have a single configuration to manage everything.
  • Code reuse — If there is a common code or a dependency that has to be used in different projects, we can actually share them easily.
  • Transparency — Gives us visibility of code used in every app.
  • Atomic changes — We can make a single change and reflect the changes in all the packages, thus making development much quicker. We witnessed this last week when a new engineer was onboarded and delivered his first feature within a month of his joining.
Some last minute deployment horror stories our team experienced.

In the end it was a team effort and everyone pitched in to get this through, especially:

  1. Sarmad for kicking off this "adventure".
  2. Taha Khalid for taking responsibility of final deployment.
  3. Arish for maintaining old portals while working on new ones.
  4. Bilal for being with us from start of this "adventure" and never hesitating in doing the non-exciting stuff.
  5. Nasir, Urooj and Muqaddas for constant refactoring they did for past few months.
  6. Asim, Mohsin and Yasha for spending hours testing each and every page.
  7. Haseeb Tariq for maintaining the old portals and learning React to kickoff one of our initial portals.

As we further build our product, we're hiring rockstar engineers to join Turing Technologies and come work on Unmudl. Our frontend is built on:

  • React, Next.js
  • TypeScript
  • Styled Components

Checkout Turing Tech's careers page for more information:

Asad Raza (Guest Writer)