Next.js SaaS
Créer un SaaS Next.js pour la production : authentification, facturation, tâches et déploiement
Créez un SaaS Next.js 16 prêt pour la production avec authentification, Postgres, abonnements, tâches en arrière-plan, configuration sécurisée, tests et déploiement.
La complexité d’un SaaS apparaît quand les fonctionnalités rencontrent la gestion de l’état : identité, autorisations, facturation, nouvelles tentatives, migrations et versions. L’arbre des composants React n’est qu’une partie du système.
Définir le premier parcours client complet
Commencez par un parcours qu’un client peut terminer : découvrir le produit, créer un compte, suivre l’accueil initial, créer la ressource principale, recevoir le résultat et revenir plus tard pour retrouver le même état. Cette démarche révèle les véritables limites du système plus tôt qu’un long inventaire de fonctionnalités.
Décrivez les transitions d’état en même temps que les écrans. Précisez qui peut effectuer chaque transition, quels enregistrements changent, quels appels externes ont lieu et ce qui se passe lorsqu’un appel se répète ou échoue. Un SaaS fiable se conçoit autour de ces transitions plutôt qu’autour d’une collection de cartes de tableau de bord.
- —Routes publiques d’acquisition et de documentation.
- —Authentification, session et récupération de compte.
- —L'objet principal du domaine et ses règles de propriété.
- —Un droit lié à la facturation ou les limites explicites de l’offre gratuite.
- —E-mails, tâches, traces d’audit et éléments de diagnostic des échecs.
Séparer le code public, applicatif et réservé au serveur
Utilisez les groupes de routes pour donner des mises en page différentes aux routes marketing et aux routes authentifiées, sans changer leurs URL. Gardez les pages et layouts en Server Components, puis ajoutez des Client Components autour des formulaires et commandes qui ont besoin de l’état du navigateur. Le contenu public reste explorable et le tableau de bord charge moins de JavaScript.
Placez l’accès à la base de données, les autorisations, les adaptateurs de facturation et les intégrations contenant des secrets dans des modules réservés au serveur. Une couche d’accès aux données centralise les lectures sécurisées pour les rendre auditables. Les Server Actions gèrent les mutations lancées par l’interface React ; les Route Handlers gèrent les webhooks, les contrôles de santé et les interfaces HTTP utilisées en dehors de cette interface.
A practical SaaS route tree
src/app/
├── (marketing)/page.tsx
├── (marketing)/pricing/page.tsx
├── (auth)/login/page.tsx
├── (app)/dashboard/page.tsx
├── (app)/projects/[id]/page.tsx
├── api/stripe/webhook/route.ts
└── api/health/route.ts
src/lib/
├── auth.ts
├── dal.ts
├── db.ts
└── billing.tsModéliser la propriété dans la base de données
Utilisez une base relationnelle pour les comptes, appartenances, données métier, droits d’accès, événements webhook et tâches qui nécessitent des transactions et des contraintes. Associez chaque enregistrement à une clé de compte ou de tenant. Imposez l’unicité et les clés étrangères dans la base pour que les opérations concurrentes ne contournent pas les hypothèses du code applicatif.
Les migrations font partie du code de production. Commencez par des ajouts, complétez les données existantes séparément si nécessaire, déployez du code capable de lire la structure transitoire, puis supprimez les anciens champs plus tard. Une version ne doit pas supposer que toutes les répliques et toutes les tâches changent de schéma au même instant.
Traiter la facturation comme un état asynchrone
Checkout amorce un processus de facturation ; il ne fait pas autorité sur l’état final de l’abonnement. Créez la session Checkout sur le serveur, redirigez vers le prestataire et mettez à jour les droits locaux à partir d’événements webhook vérifiés. Stockez les identifiants client et abonnement du prestataire auprès du compte propriétaire.
Traitez les nouvelles tentatives sans risque en enregistrant les identifiants d’événement avec une contrainte d’unicité. Gérez explicitement l’activation, les changements d’offre, les paiements échoués, l’annulation et la suppression. Décidez quelles actions exigent un droit actif et comment un délai de grâce modifie l’accès. L’interface doit lire un état de facturation local normalisé plutôt qu’interroger le prestataire à chaque page.
Sortir des requêtes les tâches lentes qui peuvent être retentées
Les e-mails, imports, exports, synchronisations avec les prestataires et générations de rapports ne doivent pas garder une requête HTTP ouverte. Enregistrez une tâche durable ou émettez un événement de workflow lors de la mutation, renvoyez un état utile à l’utilisateur et laissez un worker effectuer le travail lent avec de nouvelles tentatives et des délais limites.
Rendez les tâches idempotentes, enregistrez les tentatives et distinguez les pannes du prestataire qui permettent une nouvelle tentative des données d’entrée invalides. Le tableau de bord doit afficher les états en attente, réussis et échoués, plutôt que de faire croire que chaque action en arrière-plan se termine immédiatement.
- —Un identifiant de tâche stable et une clé de déduplication.
- —Un nombre limité de nouvelles tentatives avec délai progressif.
- —Des délais limites pour les appels externes.
- —Une erreur finale que vous pouvez examiner et un moyen de reprendre.
Tester les limites et la reprise après un échec
Testez les règles métier avec des tests unitaires, la couche d’accès aux données et les mutations avec des tests d’intégration, puis l’inscription, l’accueil initial, le workflow principal et la facturation avec des tests navigateur. Ajoutez des cas adverses : un utilisateur demande un enregistrement d’un autre compte, un webhook arrive plusieurs fois, des opérations concurrentes sollicitent une contrainte en base et un prestataire externe dépasse le délai limite.
Effectuez la compilation de production séparément du lint, de la vérification des types et des tests. Démarrez l’application compilée avec des valeurs d’environnement proches de la production, appliquez les migrations dans une étape contrôlée et effectuez des tests de bon fonctionnement sur le contenu public, les lectures authentifiées, une mutation, la route webhook et le contrôle de santé.
Déployer l’ensemble du contrat d’exécution
Adios exécute le serveur de production Next.js standard dans un processus Node.js persistant : les Server Components, les Route Handlers, les connexions à la base de données et les pages authentifiées partagent une même version de l’application. Le manifeste indique la compilation, le démarrage, le port, le chemin de contrôle de santé, les ressources et les références aux secrets, aux côtés du code source.
Déployez un aperçu, consultez les journaux de compilation et d’exécution, vérifiez les migrations et les services requis, puis promouvez la version après un contrôle de santé réussi. Les domaines personnalisés et le TLS géré restent associés à la version promue. Si une version candidate ne peut pas démarrer ou réussir son contrôle de santé, ses éléments de diagnostic restent accessibles sans qu’elle devienne la version publique opérationnelle.
adios.yaml
name: northstar-saas
build_cmd: npm ci && npm run build
start_cmd: npm start
runtime:
name: node@24
port: 3000
health_path: /api/health
requires:
- db
env:
DATABASE_URL: secret://DATABASE_URL
AUTH_SECRET: secret://AUTH_SECRET
STRIPE_SECRET_KEY: secret://STRIPE_SECRET_KEY