🏛️ Architecture multi-tenant : le pattern de référence
Un SaaS moderne suit presque toujours le même pattern hiérarchique :
- User — un compte personnel (email, mot de passe, profil)
- Organization (ou Workspace) — un espace partagé entre plusieurs users
- Project — un projet ou une ressource appartenant à une organization
Un user peut appartenir à plusieurs organizations (ex : freelance qui travaille pour 3 clients). Une organization peut avoir plusieurs membres avec différents rôles (owner, admin, member, viewer).
🗂️ Schéma de base de données type
Voici les tables essentielles d'un SaaS Next.js bien architecturé :
| Table | Rôle | Champs clés |
| users | Comptes individuels | id, email, name, avatar, created_at |
| organizations | Espaces partagés | id, name, slug, plan, owner_id |
| members | Lien user-organization | user_id, org_id, role, joined_at |
| projects | Ressources de l'organization | id, org_id, name, settings |
| subscriptions | Abonnements Stripe | org_id, stripe_id, plan, status, current_period_end |
| webhooks | Log événements Stripe | id, type, payload, processed_at |
| invites | Invitations en attente | email, org_id, role, token, expires_at |
| audit_logs | Traçabilité actions | user_id, org_id, action, metadata, created_at |
🔐 Auth : Clerk vs NextAuth pour un SaaS
| Critère | Clerk | NextAuth (Auth.js) |
| Setup | 15 minutes (UI prête) | 2-3 heures (DB à câbler) |
| Organizations natives | Oui, gérées côté Clerk | À implémenter manuellement |
| MFA | Inclus, UI prête | À coder soi-même |
| Webhooks user events | Inclus (sync DB locale) | À coder |
| Coût | Gratuit jusqu'à 10k MAU | Gratuit toujours |
| Données chez vous | Non (chez Clerk) | Oui (votre DB) |
💳 Stripe Checkout : le flux de paiement
Stripe Checkout est la solution la plus simple pour facturer un SaaS. Le flux complet en 4 étapes :
- Création d'une session — côté serveur, on appelle stripe.checkout.sessions.create avec le price ID, la URL de succès, la URL d'annulation
- Redirection — on renvoie l'URL de la session, l'utilisateur est redirigé sur la page de paiement Stripe (hébergée chez eux)
- Webhook — une fois le paiement réussi, Stripe envoie un événement à votre endpoint webhook
- Mise à jour DB — votre handler webhook met à jour la table subscriptions de votre base
🪝 Webhooks Stripe : événements à écouter
- checkout.session.completed — paiement initial confirmé, créer la subscription en DB
- customer.subscription.created — confirmation officielle du nouvel abonnement
- customer.subscription.updated — changement de plan, annulation programmée
- customer.subscription.deleted — fin effective de l'abonnement, downgrade au plan gratuit
- invoice.payment_succeeded — renouvellement réussi mensuel ou annuel
- invoice.payment_failed — paiement échoué, déclencher email de relance
⚠️ Toujours vérifier la signature Stripe sur le webhook (header stripe-signature) pour éviter qu'un attaquant ne forge un faux événement.
🎯 Onboarding multi-étapes : UX clé du SaaS
Un bon onboarding multiplie le taux de conversion. Étapes typiques :
- Inscription — email + password ou OAuth
- Email verification — magic link ou code à 6 chiffres
- Profil — nom, photo, fonction, rôle dans l'entreprise
- Organisation — créer ou rejoindre une organization
- Inviter les coéquipiers — emails séparés par virgules
- Première action de valeur — créer le premier projet, importer des données, connecter une intégration
- Tour produit — tooltips guidés sur les fonctionnalités principales
⚡ Performance : 3 piliers Next.js
- Image optimization — le composant Image redimensionne automatiquement, sert en WebP, lazy-load par défaut
- Font optimization — next/font télécharge les fonts au build, élimine le FOIT/FOUT, zero layout shift
- Code splitting — chaque route a son propre bundle JS, le navigateur ne télécharge que le code nécessaire
🏆 Lighthouse 100/100/100/100 — Checklist 8 points
- Utiliser le composant Image avec largeur et hauteur explicites
- Charger les fonts via next/font, jamais via link href Google Fonts
- Lazy-loader les composants lourds (charts, modals) avec dynamic import
- Activer la compression Brotli (Vercel le fait par défaut)
- Métadonnées SEO complètes sur chaque page (title, description, canonical, og)
- Sitemap.xml et robots.txt présents à la racine
- Attributs alt sur toutes les images, labels sur tous les inputs
- Contraste de texte minimum 4.5:1 sur tout le site
🧪 Tests : Vitest et Playwright
| Outil | Type | Cas d'usage |
| Vitest | Tests unitaires et intégration | Fonctions utilitaires, hooks, composants isolés |
| Playwright | Tests end-to-end | Parcours complets : signup, paiement, onboarding |
| Testing Library | Tests composants React | Interactions DOM, événements clavier, screen reader |
Stratégie pyramide : beaucoup d'unit (Vitest), quelques intégration, peu de E2E (Playwright). Les E2E sont lents mais protègent les parcours critiques business.
📈 Métriques de succès d'un SaaS
- MRR (Monthly Recurring Revenue) — revenu mensuel récurrent, métrique reine
- Churn — taux d'attrition mensuel des clients (objectif moins de 5 pourcent)
- LTV (Lifetime Value) — revenu total moyen généré par un client
- CAC (Customer Acquisition Cost) — coût d'acquisition d'un client
- LTV / CAC — ratio sain au-dessus de 3, ratio excellent au-dessus de 5
- Time to Value (TTV) — temps entre signup et premier moment "wow"
- Activation rate — pourcentage de signups qui complètent l'onboarding
- NPS (Net Promoter Score) — recommanderiez-vous le produit ? 0 à 10
✅ À retenir : un SaaS Next.js moderne, c'est App Router + Auth (Clerk ou NextAuth) + ORM (Drizzle ou Prisma) + Stripe + Vercel. Cette stack fait tourner des produits qui génèrent plusieurs millions de USD ARR.
🚀 La suite : aller plus loin
- Étudier des starters open source : Taxonomy (Shadcn), SaaS Starter Kit, Cal.com
- Lire la doc officielle Next.js (excellente ressource)
- Suivre Lee Robinson (VP DevX Vercel) sur YouTube et Twitter
- Construire un mini-SaaS personnel pour pratiquer toute la stack
- Rejoindre la communauté Discord Next.js (très active)