Pile de production Next.js
Valeurs par défaut structurées pour la création et la maintenance d'applications Next.js. Lors de l'échafaudage d'un nouveau projet ou de l'ajout à un projet existant, suivez ces conventions, sauf si la base de code existante de l'utilisateur fait clairement autre chose — respectez les modèles existants plutôt que ce document en cas de conflit, et notez brièvement la déviation.
0. Aperçu de la pile
| Couche | Recommandée (préférée, pas stricte) | Options à proposer si un changement est demandé |
|---|---|---|
| Framework | Next.js (App Router), TypeScript, Server Components + Server Actions | aucun nécessaire, c'est le cœur |
| Gestionnaire de paquets | pnpm | npm, yarn, bun |
| UI | Tailwind CSS, shadcn/ui, react-icons, Motion (motion.dev) | Radix UI ou Mantine, lucide-react, CSS Modules |
| Formulaires | React Hook Form + Zod | TanStack Form, Valibot au lieu de Zod |
| Base de données | PostgreSQL + Drizzle ORM | Prisma, Kysely ; MySQL ou SQLite pour les petites apps |
| Authentification | Better Auth, RBAC | Auth.js, Clerk, Supabase Auth |
| Médias | Cloudinary | UploadThing, S3 + CDN, Vercel Blob |
| Tests | Vitest (unitaire/intégration), Playwright (e2e) | Jest, Cypress |
| Surveillance | Sentry, logs structurés | Datadog, Highlight, Axiom + pino |
| Lint/Format | ESLint, Prettier, TypeScript strict | Biome |
| CI/CD | GitHub + GitHub Actions, Vercel, déploiements de prévisualisation | GitLab CI, Netlify, Cloudflare Pages |
Ne remplacez jamais silencieusement un package de ce tableau par une alternative (par exemple, Prisma au lieu de Drizzle, next-auth au lieu de Better Auth). Si le projet de l'utilisateur utilise déjà un choix différent, continuez à l'utiliser et signalez l'incompatibilité au lieu de mélanger deux solutions pour la même tâche.
Ces outils sont recommandés : l'utilisateur les préfère mais ils ne sont pas stricts.
- Partout où une section ultérieure nomme un outil spécifique (pnpm, Drizzle, Better Auth, Cloudinary, Sentry, etc.), considérez-le comme la valeur par défaut recommandée selon cette règle.
- Avant de changer, remplacer ou ignorer un outil du tableau, demandez d'abord à l'utilisateur. Proposez des options : conserver l'outil recommandé, ou une alternative de la dernière colonne (ou une autre bonne pratique), avec un compromis d'une ligne pour chacun et votre propre recommandation.
- Vérifiez le statut actuel (maintenance, changements cassants) avant de recommander une alternative. Ne vous fiez pas uniquement à votre mémoire.
- Ne changez jamais d'outil sans réponse. Jusqu'à ce que l'utilisateur réponde, conservez la valeur par défaut recommandée.
1. Configuration du projet
- Échafauder avec
pnpm create next-app@latest— TypeScript, App Router, Tailwind, ESLint tous activés ; décliner le répertoiresrc/pour queapp/reste à la racine du projet (nouveaux projets uniquement). - Projet existant qui utilise déjà
src/: conservezsrc/—src/app/,src/components/,src/lib/,src/actions/. Utilisezapp/uniquement lorsque le projet n'a pas de répertoiresrc/. Suivez la structure existante et les alias d'importation (@/*→src/*) ; ne déplacez jamais de fichiers hors desrc/dans le cadre d'une tâche non liée. - Utilisez pnpm pour chaque commande d'installation/exécution (
pnpm add,pnpm dlx,pnpm dev). Ne mélangez jamais les fichiers de verrouillage npm/yarn. - Initialisez shadcn/ui via
pnpm dlx shadcn@latest init, puis ajoutez des composants à la demande (pnpm dlx shadcn@latest add button) plutôt que de pré-installer l'ensemble complet. - Structure de dossiers de base (sans
src/—app/se trouve à la racine du projet) :
# nouveaux projets (sans src/)
app/ # routes, layouts, limites error/loading/not-found
components/ # UI partagée (ui/ = primitives shadcn)
lib/ # base de données, authentification, validations, utilitaires, limiteur de débit, journalisation
actions/ # actions serveur regroupées par domaine
hooks/
types/
drizzle/ # migrations
Projets existants avec src/ : même structure sous src/ (src/app/, src/components/, src/lib/, src/actions/) — les noms de dossiers restent identiques, seul le préfixe change.
2. TypeScript & qualité du code
strict: truedans tsconfig, pas deanysans commentaire le justifiant, pas de@ts-ignoresans problème/raison lié(e).- ESLint (next/core-web-vitals + typescript-eslint) et Prettier configurés et validés avant que le code ne soit considéré comme terminé ; exécutez-les, ne supposez pas simplement.
- Préférez les types de retour explicites sur les fonctions exportées et les Server Actions.
- Conservez les Server Components comme valeur par défaut ; ajoutez
"use client"uniquement lorsque l'interactivité, les API du navigateur ou les hooks l'exigent, et repoussez la limite aussi bas (au niveau des feuilles) que possible. - Une responsabilité par fichier/module ; colocalisez les actions serveur d'une route dans
actions/ou un fichier_actions.tsà côté de la route, et non en ligne dans d'énormes fichiers de page. - Conventions d'architecture : gardez un seul endroit pour chaque type de logique — accès aux données dans
lib/db, mutations dansactions/, UI partagée danscomponents/, aides transversales danslib/. Suivez la dénomination existante du projet (casse des fichiers, nommage des composants) plutôt que d'introduire une nouvelle convention à mi-parcours. - Révision de code : traitez chaque changement non trivial comme de la taille d'une PR — un diff clair, lint/typecheck/tests réussis avant de demander une révision, et une description de ce qui a changé et pourquoi. Lors de la révision (humaine ou assistée par IA), vérifiez les vérifications d'authentification manquantes, les erreurs non gérées et la dérive des conventions, pas seulement si le code s'exécute.
3. Rendu, données & performances
- Rendu statique vs dynamique : par défaut, optez pour le statique ; optez pour le dynamique (
export const dynamic = 'force-dynamic',cookies(),headers()) uniquement lorsque la route a vraiment besoin de données par requête. - Récupération de données : récupérez directement dans les Server Components ; utilisez les Server Actions pour les mutations, pas de requête client vers une route API, sauf si le consommateur est externe.
- Streaming & Suspense : enveloppez les sections lentes/streamables dans
<Suspense>avec un véritable squelette de secours (pas un simple spinner) afin que le reste de la page puisse être rendu et diffusé immédiatement — c'est également ce que fournitloading.tsxau niveau de la route. - Mise en cache & revalidation : utilisez
use cache/unstable_cache(selon la version de Next) pour les lectures coûteuses ; invalidez précisément avecrevalidatePath/revalidateTagaprès les mutations plutôt que d'utiliserforce-dynamicpour "corriger" la péremption. - Pré-récupération : pré-récupérez les liens que les utilisateurs sont susceptibles de suivre —
<Link>le fait automatiquement ; ne désactivez pas (prefetch={false}) sans raison spécifique. - Chargement différé & division de code : chargez en différé les composants clients situés sous la ligne de flottaison ou rarement utilisés avec
next/dynamic; évitez les gros bundles clients provenant de bibliothèques uniquement nécessaires sur une seule page. - Optimisation des images & des polices : utilisez toujours
next/imagepour les images matricielles (width/heightexplicite oufill+ conteneur dimensionné) etnext/fontpour les polices — jamais de<img>brut ou de<link>vers Google Fonts. - Core Web Vitals : traitez LCP, CLS, INP comme une contrainte réelle — pas de contenu tardif provoquant un décalage de mise en page, pas de médias non dimensionnés, pas de scripts synchrones bloquants.
4. UI
- Tailwind pour le style ; les composants shadcn/ui comme primitives de base, personnalisés via les jetons de thème du projet (variables CSS) plutôt que des remplacements en ligne ponctuels dispersés dans les fichiers.
- react-icons pour l'iconographie (choisissez un ensemble d'icônes par projet, par exemple
react-icons/luou/hi2, et restez cohérent). - Motion (motion.dev, anciennement Framer Motion) pour l'animation ; gardez les composants animés côté client et petits, et respectez
prefers-reduced-motion. - Concevez de manière réactive par défaut (points d'arrêt Tailwind mobile-first) ; ne livrez pas une mise en page uniquement pour ordinateur de bureau.
5. Formulaires & validation
- Définissez un schéma Zod par formulaire/forme de données ; réutilisez le même schéma pour la validation côté client (via
@hookform/resolvers/zod) et la validation côté serveur dans la Server Action — ne faites jamais confiance à une validation uniquement côté client. - React Hook Form (
useForm) pilote l'état côté client ; lors de la soumission, appelez une Server Action, remontez les erreurs de champ à partir de la valeur de retour structurée de l'action (pas d'exceptions levées qui aboutiraient à une erreur générique). - Validez
process.envlui-même avec un schéma Zod au démarrage (unlib/env.ts) afin qu'une configuration manquante/malformée échoue rapidement au lieu de le faire lors de la première utilisation.
6. Base de données (PostgreSQL + Drizzle)
- Le schéma se trouve dans
lib/db/schema.ts(ou divisé par domaine), les migrations générées viadrizzle-kit generateet appliquées viadrizzle-kit migrate— ne modifiez jamais manuellement les fichiers de migration générés. - Utilisez une connexion poolée (par exemple via le pool du pilote ou un fournisseur comme Neon/Supabase pooling) dans les contextes serverless/edge ; n'ouvrez pas un nouveau client par requête sans mise en pool.
- Optimisation des requêtes & prévention des N+1 : utilisez les requêtes relationnelles de Drizzle (
db.query.x.findMany({ with: {...} })) ou des jointures explicites au lieu de boucler et d'interroger ligne par ligne ; sélectionnez uniquement les colonnes dont vous avez besoin au lieu de récupérations complètes de lignes de typeselect *; paginez/limitez toute requête qui peut renvoyer un ensemble de résultats illimité. - Indexez les colonnes utilisées dans
WHERE/ORDER BY/les jointures ; ajoutez-les dans le schéma, pas après coup. - Conservez une procédure de sauvegarde/restauration documentée pour les bases de données de production (instantanés du fournisseur géré au minimum) — signalez-le si la configuration de l'utilisateur n'en a aucune.
7. Authentification & sécurité
- Better Auth pour l'authentification (sessions, fournisseurs OAuth, email/mot de passe selon les besoins) ; ne faites jamais vous-même le hachage de mots de passe ou les jetons de session.
- RBAC : modélisez les rôles/autorisations explicitement (une colonne
roleplus un petit assistant de vérification des autorisations) et appliquez l'autorisation dans la Server Action / la couche d'accès aux données, pas seulement en masquant l'UI — un bouton caché n'est pas un contrôle d'accès. - Limitez le débit des points de terminaison sensibles (authentification, soumissions de formulaires, tout ce qui est coûteux) — par exemple via Upstash Redis ou un limiteur à seau de jetons/fenêtre glissante équivalent.
- Définissez des en-têtes de sécurité (via
next.config.jsou le middleware) :Content-Security-Policy,X-Frame-Options,Referrer-Policy,Permissions-Policy,Strict-Transport-Security. - Cookies :
httpOnly,secure,sameSite: 'lax'(ou'strict'lorsque c'est possible) sur tous les cookies d'authentification/session. - Validez chaque entrée externe (données de formulaire, paramètres de requête, charges utiles webhook) avec Zod à la frontière avant qu'elle n'atteigne la logique métier ou la base de données.
- Ne journalisez jamais les secrets, jetons ou corps de requête complets contenant des informations d'identification.
8. SEO
- Utilisez l'API Metadata (
generateMetadata/ exportmetadatastatique) par route — titre, description, Open Graph, Twitter card. - Fournissez
app/sitemap.tsetapp/robots.tsgénérés à partir de données de route réelles, pas d'une liste statique obsolète. - Définissez les URL canoniques via
alternates.canonicaldes métadonnées, en particulier sur toute route accessible via plusieurs variantes de chaîne de requête. - Ajoutez des données structurées JSON-LD pour les types de contenu qui en bénéficient (articles, produits, fils d'Ariane, organisation) à l'aide d'une balise script avec
type="application/ld+json".
9. Accessibilité
- HTML sémantique d'abord (
button,nav,main,header,label) — recourez à ARIA uniquement pour combler un véritable vide que le HTML sémantique ne peut pas couvrir. - Tout est accessible et utilisable au clavier uniquement ; états de focus visibles (ne supprimez pas les contours
:focus-visiblesans les remplacer). - Chaque image a un
altsignificatif (alt=""vide uniquement pour les images purement décoratives). - Chaque entrée de formulaire a une
<label>réelle associée (pas seulement un placeholder). - Vérifiez le contraste des couleurs par rapport au WCAG AA au minimum pour le texte et les éléments interactifs.
10. Gestion des erreurs & états de chargement
Chaque segment de route qui peut échouer ou prendre du temps doit avoir :
error.tsx— limite d'erreur au niveau du segment avec une action de réessai.global-error.tsx— solution de secours de niveau supérieur pour les erreurs queerror.tsxne peut pas attraper.not-found.tsx— pour les 404, y compris les appelsnotFound()issus de recherches de données.loading.tsx— solution de secours Suspense ; faites-en un véritable squelette correspondant à la disposition finale, pas un simple spinner.
11. Tests
- Vitest pour les tests unitaires (fonctions pures, validation de schéma, logique utilitaire) et les tests de composants (React Testing Library) — colocalisez-les en tant que
*.test.ts(x)ou sous__tests__/. - Playwright pour les flux de bout en bout : authentification, parcours utilisateur critiques, soumissions de formulaires. Exécutez-les contre un déploiement de prévisualisation ou une build locale, pas contre la production.
- Les nouvelles Server Actions et les schémas de validation doivent être livrés avec au moins un test de base ; ne laissez pas la logique métier critique non testée par défaut.
12. Surveillance & journalisation
- Sentry pour le suivi des erreurs côté client et serveur (fichier d'instrumentation +
sentry.client.config/sentry.server.config), avec les source maps téléchargées lors du déploiement. - Journalisation structurée (logs JSON avec identifiant de requête, route, identifiant utilisateur lorsque disponible) au lieu de
console.logponctuels. - Suivez les Core Web Vitals en production (Vercel Analytics ou Sentry Performance) et configurez une surveillance de disponibilité sur l'URL déployée.
13. DevOps
- Git avec des commits conventionnels et cadrés ; branche
mainprotégée. - CI GitHub Actions sur chaque PR : installation → lint → typecheck → tests unitaires → build (ajoutez e2e pour les changements plus importants).
- Déployez sur Vercel ; chaque PR obtient un déploiement de prévisualisation avant la fusion.
- Variables d'environnement gérées par environnement dans Vercel, validées au démarrage via le schéma Zod env de la section 5.
14. Médias
- Cloudinary pour les médias téléchargés par l'utilisateur/dynamiques : téléchargez via des paramètres de téléchargement signés et émis par le serveur (n'exposez jamais le secret API côté client), et servez via les URL de transformation de Cloudinary au lieu de réimplémenter le redimensionnement.
15. Conventions de travail pour Claude
Lorsqu'il est demandé d'ajouter une fonctionnalité dans un projet utilisant cette pile :
- Vérifiez le schéma/les actions/les composants existants avant d'en créer de nouveaux — étendez, ne dupliquez pas.
- Nouveaux champs DB → mettez à jour
schema.ts, générez une migration, ne modifiez pas le SQL à la main. - Nouveau formulaire → schéma Zod → formulaire RHF → Server Action avec revalidation côté serveur et une vérification d'autorisation.
- Nouvelle route → décidez délibérément entre statique et dynamique ; ajoutez
loading.tsx/error.tsxsi manquant ; ajoutez des métadonnées. - Après une mutation, revalidez le chemin/la balise spécifique affecté(e) — ne revalidez pas toute l'application en bloc.
- Exécutez mentalement lint/typecheck en mode strict avant de présenter le code ; signalez tout
any, entrée non vérifiée ou vérification d'authentification manquante plutôt que de le livrer silencieusement. - Avant d'introduire, remplacer ou ignorer un outil de la section 0, demandez à l'utilisateur avec des options (voir la règle "Recommandé, pas strict" dans la section 0).
16. Fichier de règles compagnon
AGENTS.md— la règle de flux de travail du projet (Flux principal, Flux de fonctionnalité, approbation ga