Aller au contenu
Supastack
FR
Thème
Se connecterObtenir Supastack
Tous les articles

Construire un SaaS Web et Mobile avec Next.js et Expo (Guide Monorepo)

Guide d'architecture SaaS multiplateforme : unifier Next.js 16 et React Native Expo au sein d'un monorepo pnpm avec Better Auth et Drizzle ORM partagés.

Noah Zixin Zhang2 min de lecture

Comment partager du code entre Next.js et Expo dans un monorepo ?

Cela dépend de vos frontières de modules et de la configuration des bundlers. La méthode la plus robuste consiste à utiliser pnpm et Turborepo pour isoler modèles de données, schémas de validation et contrats d'API dans des paquets internes agnostiques. Le serveur Next.js 16 exécute Drizzle ORM directement contre PostgreSQL, tandis que l'application Expo communique via des points d'accès HTTP typés et conserve les jetons de session dans expo-secure-store. supastack préconfigure l'ensemble sans conflit entre Metro et Turbopack.

Le principal écueil du SaaS multiplateforme : La friction entre bundlers

Chaque fondateur mesure à quel point une application mobile renforce l'engagement et la rétention grâce aux notifications push et à la présence sur l'écran d'accueil. Cependant, marier Next.js et React Native Expo dans un même dépôt pose souvent problème.

Next.js s'appuie sur Turbopack ou Webpack dans les environnements Node et Edge, alors qu'Expo exploite le bundler Metro dédié à React Native. Les tentatives informelles de partage de code débouchent vite sur des erreurs : Metro tente de charger des bibliothèques Node comme crypto, tandis que Turbopack bloque sur des syntaxes JSX mobiles. Une encapsulation rigoureuse en paquets résout ce dilemme.

Conception de paquets partagés : Authentification, schémas et contrats

Dans une architecture propre, les applications clientes (apps/web et apps/mobile) se limitent à l'affichage. La logique métier et les structures de données résident dans des paquets internes sous packages/ :

@supastack/db : Rassemble les tables Drizzle ORM, les relations et les migrations. Seul le serveur se connecte à la base ; les clients n'importent que les types TypeScript déduits.

@supastack/auth : Configure Better Auth avec deux points d'entrée : les routes serveur et un kit client agnostique utilisé par le Web et le Mobile.

@supastack/config : Valide les variables d'environnement à la compilation avec Zod pour éliminer tout plantage en production lié à un réglage manquant.

// 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 })] : [],
  });
}

Authentification unifiée : Cookies pour le Web, SecureStore sur Mobile

Le Web et le Mobile reposent sur des mécanismes de persistance distincts. Sur navigateur, Next.js génère des cookies HTTP-only avec SameSite=Lax, assurant la protection CSRF et l'hydratation fluide des Server Components.

Sur smartphone, les cookies manquent de fiabilité dans les WebViews. L'application Expo extrait un jeton de session Bearer à l'issue du flux OAuth ou du lien magique, puis le consigne dans le trousseau iOS ou le Keystore Android via expo-secure-store. Les requêtes mobiles transmettent ce jeton dans l'en-tête Authorization: Bearer <token>, validé par le middleware partagé de Better Auth.

Pipeline CI/CD et déploiement : Vercel, EAS Build et synchronisation

Administrer le Web et le Mobile dans un dépôt unique garantit des mises en production parfaitement coordonnées. Lorsqu'une migration est validée dans @supastack/db, le backend Next.js se déploie instantanément sur Vercel ou Cloud Run.

Parallèlement, les services EAS Build d'Expo génèrent les binaires natifs pour Apple TestFlight et Google Play. En figeant les versions des paquets partagés, vous supprimez définitivement les écarts de version propres aux dépôts séparés.

Votre prochain produit commence ici.

Payez une fois. Créez des produits rentables.