Pour commencer · 3 min
Structure du projet
Où tout se trouve et, plus utile encore, où regarder quand quelque chose de précis est cassé.
src/
app/
api/checkout/route.ts ouvre une session Stripe Checkout
api/webhooks/stripe/route.ts la livraison : le seul endroit où une vente devient réelle
auth/callback/route.ts transforme un lien magique en cookie de session
app/layout.tsx la coque connectée. requireUser tourne ici, donc
toute route en dessous est protégée
app/page.tsx le tableau de bord
app/settings/ profil, langue, suppression du compte
admin/layout.tsx requireAdmin tourne ici, même raisonnement
admin/ derrière ADMIN_EMAILS
blocks/ la galerie de blocs et trois gabarits de page.
Développement seulement, voir Composants
blog/ articles MDX
blog/feed.xml/route.ts le flux RSS, bâti sur les mêmes articles
sign-in/page.tsx
layout.tsx polices, locale, thème, providers
globals.css tous les tokens de design
sitemap.ts robots.ts icon.tsx opengraph-image.tsx
components/
blocks/ quinze sections de page. À copier, pas à configurer
ui/ Card, Field : les deux que vous réutiliserez
OAuthButtons SignInForm SignOutButton LocaleSwitcher CopyField
lib/
auth.ts currentUser, requireUser
admin.ts la liste d'accès. server-only, délibérément
validation.ts schémas Zod partagés par le formulaire et l'action
ratelimit.ts adossé à Postgres, échoue en laissant passer
observability.ts Sentry ou Datadog derrière une seule interface
supabase/server.ts les deux clients serveur
supabase/client.ts le client navigateur
stripe.ts email.ts blog.ts store.ts i18n.ts i18n.server.ts
paraglide/ généré. Ne jamais éditer, ne jamais relire
messages/
en.json fr.json la source de vérité pour les textes
content/blog/ les articles, en fichiers
supabase/schema.sql tables, politiques, triggers
e2e/ Playwright, contre un vrai build
scripts/setup.mjs scripts/db-push.mjs scripts/doctor.mjs
Dockerfile compose.yaml multi étages, sans root
proxy.ts tourne à chaque requête
Où regarder quand
| Symptôme | Fichier |
|---|---|
| Connecté, puis déconnecté aussitôt | proxy.ts, puis auth/callback/route.ts |
| Le lien magique s'ouvre et ne fait rien | Les modèles d'e-mail Supabase, voir Authentification |
| Paiement passé, mais rien ne s'est produit | api/webhooks/stripe/route.ts et le journal d'événements Stripe |
| Mauvais montant débité | api/checkout/route.ts. Le prix vient de la base, jamais de la requête |
Le texte affiche {name} littéralement | messages/*.json, voir Internationalisation |
| Un token de couleur ne fait rien | app/globals.css. Un token doit être déclaré dans @theme avant que Tailwind n'émette la classe |
| Un utilisateur lit la ligne d'un autre | supabase/schema.sql. C'est une policy, pas du code applicatif |
proxy.ts
Next.js 16 a renommé le middleware. Le fichier s'appelle proxy.ts, à la
racine, et il exporte proxy, pas middleware. Si vous copiez un extrait d'un
article écrit avant le renommage, c'est pour cela qu'il ne fait rien.
Il s'exécute à chaque requête et fait une seule chose : rafraîchir le cookie d'authentification. Les Server Components ne peuvent pas écrire de cookies, donc sans lui une session expire en pleine visite et l'utilisateur est déconnecté au milieu du paiement.
src/paraglide
Généré par le compilateur de messages. Le dossier est commité pour qu'un clone propre se construise sans lancer le compilateur d'abord, mais vous ne l'éditez jamais et il n'y a aucun intérêt à le lire dans un diff. Si vous voyez trois cents fichiers modifiés là-dedans, c'est que vous avez ajouté un message.
Les deux clients Supabase
C'est la distinction qui piège, elle vaut la peine d'être apprise tôt.
supabaseServer() // agit comme l'utilisateur connecté. RLS s'applique. Par défaut.
supabaseAdmin() // agit comme le rôle de service. RLS ne s'applique pas.supabaseAdmin() existe pour le webhook, qui n'a pas d'utilisateur et doit
écrire des lignes qu'aucun utilisateur n'a le droit d'écrire. Y recourir parce
qu'une requête n'a rien renvoyé, c'est ainsi qu'on livre une application où
chaque utilisateur lit toutes les lignes. Si supabaseServer() ne renvoie rien,
le bug est dans la policy.
Une erreur ou un manque sur cette page ? Dites-le-nous.