Pourquoi ce sujet est important
App Router facilite le rendu serveur, les layouts et le chargement des données, mais n’impose pas une architecture métier. Sans règles, les routes accumulent requêtes, validation et composants client difficiles à tester.
Organiser par responsabilités
Le dossier app décrit les URL, layouts, états loading et error et points d’entrée. Gardez la logique métier dans des modules indépendants, par domaine ou fonctionnalité. Les composants partagés restent dans une bibliothèque UI. Évitez un immense dossier utils sans propriétaire.
Server Components par défaut
Les composants serveur peuvent accéder aux données et garder secrets et dépendances lourdes hors du navigateur. Ajoutez use client seulement à la frontière nécessitant état, événements ou API navigateur. Un composant client entraîne ses imports dans le bundle client.
Créer une couche d’accès aux données
Centralisez les requêtes dans des fonctions serveur validant identité, autorisation et erreurs. Retournez des objets adaptés à l’interface plutôt que les lignes brutes. Cette couche facilite tests, cache et changement de source. Ne faites pas confiance aux paramètres de route.
Comprendre cache et fraîcheur
Définissez explicitement ce qui peut être mis en cache, combien de temps et comment invalider. Les pages publiques, tableaux privés et prix temps réel n’ont pas la même politique. Testez après mutations et déploiement. Une donnée personnelle ne doit pas entrer dans un cache partagé.
Mutations et Server Actions
Une action serveur reste un endpoint : validez entrée, session, droits et idempotence. Gérez erreurs attendues sans exposer la stack. Après écriture, invalidez les données concernées ou redirigez. Les opérations critiques nécessitent transactions et journalisation.
Gérer les limites de route
Utilisez page pour composer, layout pour partager l’interface, loading pour le streaming et error pour la récupération locale. Les Route Handlers servent une API lorsque nécessaire. Évitez de dupliquer une API interne si un appel serveur direct suffit.
Tester
Testez les modules métier sans Next.js, puis les fonctions d’accès et composants importants. Ajoutez tests de navigation et autorisation. Vérifiez bundle client, performance et accessibilité. Les règles d’import peuvent empêcher le code serveur d’entrer côté client.
Exemple concret
Un site éditorial garde les routes dans app, les requêtes Payload dans data, les règles de publication dans domain et les composants visuels dans components. La page assemble des Server Components ; seul le filtre interactif devient client. Les tests métier n’ont pas besoin de lancer Next.js.
Les erreurs fréquentes
- mettre use client au niveau du layout racine
- interroger la base depuis chaque composant
- mélanger validation et JSX
- cacher des données utilisateur globalement
- traiter une Server Action comme une fonction de confiance
- organiser uniquement par type de fichier
Checklist
- [ ] Routes limitées à la composition
- [ ] Server Components par défaut
- [ ] Couche data server-only
- [ ] Autorisation dans le serveur
- [ ] Cache et invalidation explicites
- [ ] Actions validées et idempotentes
- [ ] Modules métier testables
- [ ] Bundle client surveillé
FAQ
Faut-il un dossier src ?
C’est un choix d’organisation. La cohérence des frontières compte davantage.
Quand utiliser un Client Component ?
Pour état interactif, événements ou API navigateur, au niveau le plus bas possible.
Faut-il appeler sa propre API depuis le serveur ?
Pas généralement. Appelez directement la couche de données sauf besoin d’une vraie frontière réseau.
Où mettre les types ?
Près du domaine propriétaire, ou générés depuis le schéma lorsqu’il constitue la source de vérité.
Exemple d’arborescence par domaine
~~~text src/ ├── app/ │ ├── (marketing)/page.tsx │ ├── (dashboard)/ │ │ ├── dashboard/page.tsx │ │ └── settings/page.tsx │ ├── api/webhooks/route.ts │ ├── error.tsx │ └── layout.tsx ├── features/ │ └── billing/ │ ├── components/ │ ├── queries.ts │ └── schemas.ts └── lib/ ├── auth.ts └── db.ts ~~~
Les groupes entre parenthèses organisent sans modifier l’URL. Placez loading.tsx, error.tsx et not-found.tsx au segment pertinent. Les pages orchestrent ; la logique métier appartient aux domaines. Chargez les données dans les Server Components et placez use client aussi bas que possible. Évitez un dossier global de composants sans règles.