Monorepo architecture: 4 apps, 1 Supabase instance

By Ahmed "Riz" Ratul · 2026-03-24 03:48:13 · Architecture, React Native

How we structure a monorepo with iOS, Android, web, and admin sharing one Supabase backend.

The mymuaythai.app monorepo has four apps:

1. Mobile (Expo SDK 53, React Native 0.79) — iOS and Android

2. Web (React 18, Vite 5) — Public-facing website

3. Admin (React 19, Vite 7) — Internal dashboard

4. Job Board (Next.js) — Public job listings

All four share one Supabase instance. Here's how we make that work without chaos.

Shared packages

  • <code>@repo/supabase</code> — Generated types from <code>supabase gen types</code>, shared client config
  • <code>@repo/shared</code> — Business logic, validation schemas (Zod), constants
  • <code>@repo/ui</code> — Shared UI components (limited — mobile and web have different needs)
  • The type generation pipeline

    When the schema changes: supabase db pushsupabase gen types → all four apps get updated types. One migration, all surfaces updated. TypeScript catches breakage at compile time.

    What we don't share

    Routing, state management, and most UI. Mobile uses Expo Router + Zustand. Web uses React Router. Admin uses Vite's built-in routing. Trying to share too much across platforms is a trap.

    The overhead is worth it

    A monorepo adds tooling complexity. But when you fix a bug in a shared validation schema, it's fixed everywhere. When you add a database column, TypeScript tells you every file that needs updating. That compound benefit is enormous.