Here's how ditching a "universal" app helped us ship new products in just two days.
Why a single app doesn’t work anymore
Remember the days when one app tried to do everything at once? One registration flow, a role-based interface, and logic that was supposed to work for everyone. That’s exactly how Uber started – one app for both riders and drivers. Until things got too big. Too complex. Too heavy. Eventually, they split the app into Uber and Uber Driver. Same with Glovo, Bolt, DoorDash. And that was the right call.
Because when you cram the client, the riders, support, and operations into a single app – it stops being a product and starts turning into Frankenstein. It grows, it conflicts with itself, and one day it risks collapsing under its own weight.
In this article, I’ll walk you through how our team helped Sizl – a dark kitchen service in Chicago – split its platform into three standalone products. This allowed us to ship faster, iterate smarter, and build on shared architecture without reinventing the wheel every time.
Our dev background
We didn’t jump into ecosystems right away. One of our earlier projects was a beauty booking service where a single app served both clients and service providers. The interface adapted to the user’s role, and everything seemed logical at first. But as the product grew, so did the problems.
As the business logic became more complex, with more use cases and edge cases, there was more room for things to break. Even a small change in one area could easily cause an issue elsewhere.

That’s when we decided to stop cramming everything into a single app.
We put this new approach to the test on our next major project – a custom-built loyalty platform in the crypto space. End users earned rewards for completing actions, while brands got detailed analytics on their behavior. The platform included Shopify integrations, a brand dashboard, a mobile app, a Chrome extension, and backend services – all custom-built from scratch.
From the start, we knew the project would be large and fast-growing. So we set the foundation right. One language – TypeScript. One set of rules – shared configs, strict linters, unified formatting. And instead of scattering features across dozens of repos, we built a centralized monorepo with clear structure and reusable modules.
The whole process is described here.
That decision paid off: onboarding new developers got easier, builds were faster, and the overall code quality stayed consistent across the board. And when it was time to build our next ecosystem – for Sizl – we already had a proven playbook.

Searching for a dev team? Tell us about your project!
From rebuild to ecosystem
Our work with Sizl began with a common request: to rebuild and improve an existing app. The client already had a working product for a dark-kitchen network in Chicago — with delivery, pickup, and a loyal user base. However, the initial version was built using Kotlin Multiplatform, a powerful yet niche technology.
As Sizl’s internal team reorganized, its founders realized that providing future support, scaling operations, and developing new features could be challenging.
We kicked off by migrating the app to React Native and adding new features. The existing product already had real data, well-defined user flows, and working business logic – a dream scenario for developers. We didn’t need to reinvent anything. Just rebuild it the right way and start improving from there.
Sizl: How we became the tech partner for the Chicago-based Dark Kitchen Network
Check out the full Siz’s case here
One codebase, many use cases
I suggested using a monorepo because I had previously built a similar setup in a TypeScript project. This allowed me to quickly see how we could connect independent pieces of code into a maintainable ecosystem.
We structured the architecture so that each part of the system – for example, authentication – became its own module, with its own logic, UI, hooks, and data. These modules lived in separate directories and didn’t depend on each other directly.

If we needed the same authentication logic in another app – say, a riders app or a partner portal – we didn’t copy-paste code or import files directly. Instead, we injected it as an external dependency. This means the module is passed in as a parameter where it’s needed, without tight coupling to the source code.
This setup made scaling easier, reduced the risk of bugs, and allowed us to reuse logic across apps without duplication.
So when the client later asked, “Can we build a separate app for riders?”, we didn’t start from scratch. Most of the core logic was already written — we just connected it via the monorepo and avoided creating redundant code.

Building a product with scale in mind? Let’s talk about its architecture
Max B. CEO
What’s inside the Sizl monorepo
We split the monorepo into two main sections:
- packages – shared modules like the API client, reusable UI components, and utilities (e.g., for formatting, date/time handling, or data parsing);
- apps – two separate frontends: one for end users and another for riders.
This structure allowed us to spin up the riders app quickly. We simply connected the necessary modules, plugged in the logic, and wired up the API. On the client side, we only had to swap out a few imports, and nothing broke.

This approach drastically sped up delivery. We shipped the riders app in about 2.5 weeks. Setting up the monorepo took around a week. The next app, a lightweight support interface, is expected to take just two days. The process is very simple, and we already have most of the necessary components.
If the backend had been written in Node.js, we would’ve included it in the monorepo too. We could have packaged the API client and imported it directly instead of regenerating the documentation every time, which would have made the integration between the front end and the back end even smoother.
Why a monorepo is worth it
A monorepo isn’t magic — it’s an engineering choice that requires significant effort initially. However, if you’re developing a substantial digital platform (rather than just testing MVPs), those investments will pay off quickly:
- Instant updates across apps. Found a bug in token refresh logic? Fix it once — and it’s resolved everywhere. No copy-pasting, no syncing headaches.
- Code quality stays consistent. One fix, global effect. Shared modules keep behavior aligned across the ecosystem.
- Future-proof evolution. As long as the tech is alive (and React Native definitely is), we can improve, optimize, and scale everything — in one place, with confidence.
But the biggest impact is what users feel: smoother flows, clearer paths, and more intuitive UX. The development team will also benefit from a cleanly separated yet connected architecture, clear responsibilities, and a setup where "just tweak it here" won't lead to "oops, we broke production."