Case study №01
One monorepo, 13 apps
Building a consumer-app factory with SvelteKit, Capacitor and tRPC
- Role
- Platform engineer
- Timeline
- Feb 2025 — Present
- Scale
- 3.3M+ users
Context
IndiDino builds consumer apps for the Indian market — dating, AI companions, astrology, learning. The ambition was a portfolio of products, not one: find what resonates, double down, keep shipping. The engineering team is small, so the usual answer — one codebase, one team, one app — was never going to get there.
The problem
Shipping N apps normally costs N× everything: N codebases, N auth flows, N payment integrations, N release processes, N sets of store builds. The goal was to make app number thirteen cost roughly a config file plus its own screens — and nothing else.
The architecture
A pnpm monorepo. Each app is a thin SvelteKit + Capacitor shell over shared packages: a UI kit, authentication (OTP, Google, Apple, Truecaller), payments (Razorpay, Google Pay, Apple Pay, UPI, wallets), notifications (FCM delivery, deep-link routing, 60+ templates) and analytics. A type-safe tRPC API on Node talks to PostgreSQL through Kysely, with pg-boss for background jobs and ClickHouse for behavioral events.
Cross-cutting systems live below the app layer, so they work for every app automatically — the fraud pipeline (device fingerprinting that blocks banned users from re-registering on any of the 13 apps) and the AI moderation pipeline (a multi-provider vision-LLM architecture, benchmarked across 6 models, running at ~$0.30 per 1,000 images) were each built once.
Key decisions
Chose a monorepo over a repo per app
One dependency graph and atomic cross-app changes: a fix to the payments package lands in every app in the same commit. The cost is CI time and ownership discipline — a platform change can break thirteen apps at once, which is what pushed us to centralized release management.
Chose Capacitor over React Native or native teams
The web team ships the native apps. The cost surfaced on iOS — plugins for biometrics, permissions, payments and media processing didn't exist the way we needed them, so I ended up owning native plugin development to keep iOS at parity with Android.
Chose tRPC end-to-end types over REST + hand-written clients
Schema drift between frontend and backend simply stopped being a failure mode; refactors became mechanical. The coupling it creates between FE and BE releases is real — and is exactly the coupling a monorepo makes cheap.
Chose shared packages over copy-paste per app
A paywall improvement or a notification-template fix ships to every app at once. In exchange, nothing platform-level can be merged casually: every change is a change to thirteen products.
Outcomes
- 13
- apps in production
- 3.3M+
- users served
- 350+
- banned users blocked platform-wide
The platform is the product: paywalls, A/B-tested onboarding funnels, authentication and push campaigns are built once and tuned per app with data from ClickHouse.
Next case study
Hidnn: dev, PM & QA