Skip to content
Supastack
EN
Theme
Sign inGet Supastack
All articles

How to Build a Web + Mobile SaaS with Next.js and Expo (Monorepo Guide)

A production guide to building a cross-platform SaaS with Next.js 16 and React Native Expo in a pnpm monorepo with shared Better Auth and Drizzle ORM.

Noah Zixin Zhang2 min read

How do you share code between Next.js and Expo in a monorepo?

It depends on your module boundaries and bundling setup. The most robust architecture uses pnpm and Turborepo to isolate shared database models, validation schemas, and API contracts into headless internal packages. Next.js 16 server actions and route handlers execute Drizzle ORM directly against PostgreSQL, while the Expo mobile app communicates with these handlers over typed HTTP endpoints, persisting authentication tokens securely via expo-secure-store. supastack preconfigures this exact monorepo structure with zero bundler resolution conflicts between Metro and Turbopack.

The Hardest Part of Cross-Platform SaaS: The Bundler Seam

Every SaaS founder eventually realizes that a mobile app dramatically increases retention, engagement, and daily active usage through push notifications and home-screen presence. However, pairing Next.js with React Native Expo in a single monorepo is notoriously painful.

Next.js relies on Turbopack or Webpack with Node.js and Edge runtime semantics, while Expo relies on the Metro bundler with React Native JavaScript runtimes. Naive attempts to share code result in instant bundling failures: Metro attempts to parse Node.js standard libraries like crypto or stream, while Turbopack fails on React Native JSX syntax. The secret to a seamless cross-platform monorepo is strict package encapsulation.

Designing Headless Shared Packages: Auth, Schema, and Contracts

In a production monorepo, applications (apps/web and apps/mobile) should be thin presentation shells. Business logic, database schemas, and authentication configuration reside in internal packages under packages/:

@supastack/db: Contains Drizzle ORM table definitions, relations, and migration files. Only server runtimes import database clients; client bundles import only inferred types.

@supastack/auth: Contains Better Auth configuration with two distinct entry points: a server-side entry point for route handlers and a headless client SDK that both web and mobile invoke.

@supastack/config: Validates environment variables using Zod at build time, preventing runtime crashes across environments.

// packages/auth/src/client.ts
import { createAuthClient } from "better-auth/react";
import { expoClient } from "@better-auth/expo/client";

export function createCrossPlatformAuthClient(baseURL: string, storage?: any) {
  return createAuthClient({
    baseURL,
    plugins: storage ? [expoClient({ scheme: "myapp", storage })] : [],
  });
}

Unified Authentication: Cookies on Web, SecureStore on Mobile

Authentication requires different persistence mechanisms on web versus mobile. On the web, Next.js sets HTTP-only, SameSite=Lax cookies that provide automatic CSRF protection and seamless Server Component hydration.

On mobile, cookies are unreliable across OS web views. Instead, the Expo app captures a secure bearer session token during OAuth or magic link exchange, storing it inside iOS Keychain or Android Keystore via expo-secure-store. Outgoing mobile API requests attach this token via the Authorization: Bearer <token> header, which the shared Better Auth middleware validates transparently.

CI/CD and Release Pipeline: Vercel, EAS Build, and Versioning

Maintaining web and mobile in one repository unlocks synchronized deployments. When a database migration lands in @supastack/db, the Next.js backend deploys to production instantly on Vercel or Cloud Run.

Simultaneously, Expo Application Services (EAS Build) compiles native binaries for Apple TestFlight and Google Play Internal Testing. By locking shared package versions across the monorepo, you eliminate the version skew bugs that plague teams maintaining separate web and mobile repositories.

Your next product starts here.

Pay once. Keep building profitable products.