E-commerce
Une boutique en ligne simple : catalogue, panier, paiement réel via Stripe.
RĂ©utilisable vs spĂ©cifique : les Ă©tapes rĂ©utilisable sont valables pour n'importe quel projet de ta stack. Les Ă©tapes spĂ©cifique sont propres Ă cette boutique â adapte le catalogue Ă tes propres produits.
Initialiser le projet Next.js
Un projet Next.js qui dĂ©marre en local, avec Tailwind et shadcn/ui prĂȘts Ă l'emploi.
Prérequis : Node.js installé. Terminal ouvert dans le dossier du projet.
-
Installe pnpm si besoin
npm install -g pnpm
pnpm est le gestionnaire de paquets choisi pour ce projet â plus rapide et plus Ă©conome en espace disque que npm.đ Comment voir le rĂ©sultat : tapepnpm -v. Un numĂ©ro de version s'affiche (ex.9.12.0) â sinon l'installation a Ă©chouĂ©. -
Crée le projet Next.js
pnpm create next-app@latest . --typescript --tailwind --eslint --app --src-dir=false --import-alias "@/*"
Le nom du dossier ne doit pas contenir de majuscules (contrainte npm). S'il en contient, crĂ©e le projet dans un dossier temporaire au nom valide puis dĂ©place tout son contenu dans ton dossier de travail.đ Comment voir le rĂ©sultat : tapels. Tu dois voir apparaĂźtreapp/,package.json,tailwind.config.tsâ la commande a rempli ton dossier de fichiers. -
Initialise shadcn/ui
pnpm dlx shadcn@latest init
Ăa crĂ©ecomponents.jsonetlib/utils.ts, et prĂ©pare Tailwind pour recevoir des composants shadcn/ui prĂȘts Ă copier.đ Comment voir le rĂ©sultat : tapels components.json lib/utils.tsâ les deux fichiers doivent exister, sans message d'erreur « No such file ». -
Crée l'arborescence du projet
mkdir -p lib/auth lib/db lib/validations prisma tests
On sĂ©pare dĂšs le dĂ©part : authentification, accĂšs base de donnĂ©es, schĂ©mas de validation. Ăa Ă©vite le fichier fourre-tout de 2000 lignes plus tard.đ Comment voir le rĂ©sultat : tapels libâ les dossiersauth,db,validationsdoivent apparaĂźtre. -
Initialise Git et fais le premier commit
git init git add -A git commit -m "chore: init projet Next.js"
đ Comment voir le rĂ©sultat : tapegit log --onelineâ une ligne avec ton message de commit doit s'afficher. -
Lance le serveur et vérifie
pnpm dev
Ouvrehttp://localhost:3000. Si tu as une erreur 500 mentionnant un module introuvable (ex.Can't resolve 'xxx') alors qu'il est bien danspackage.json: supprimenode_modules,pnpm-lock.yamlet.next, relancepnpm installpuispnpm dev. C'est presque toujours une installation incomplĂšte, pas un bug de code.đ Comment voir le rĂ©sultat : dans ton navigateur, ouvrelocalhost:3000. Tu dois voir la page d'accueil par dĂ©faut de Next.js. Le terminal afficheReadyet n'affiche pas d'erreur rouge.
Base de donnĂ©es â Prisma + Supabase
Une base PostgreSQL en ligne, avec les tables Produit, Commande et LigneCommande créées via Prisma.
Prérequis : étape 1 validée.
-
CrĂ©e un projet sur SupabaseVa sur supabase.com â New project. Choisis un nom, une rĂ©gion proche, et un mot de passe de base de donnĂ©es â note-le quelque part.đ Comment voir le rĂ©sultat : le tableau de bord Supabase affiche ton projet avec un statut « Active » (aprĂšs ~1-2 minutes).
-
RĂ©cupĂšre l'URL de connexionDans le projet Supabase : Project Settings â Database â Connection string, mode URI. Copie l'URL complĂšte (mot de passe inclus).
-
Installe Prisma
pnpm add prisma --save-dev pnpm add @prisma/client pnpm dlx prisma init
CrĂ©eprisma/schema.prismaet un fichier.envavec une variableDATABASE_URLvide.đ Comment voir le rĂ©sultat : tapels prisma/schema.prismaâ le fichier doit exister. -
Colle l'URL dans
.env# .env DATABASE_URL="postgresql://postgres:[MOT-DE-PASSE]@[HOST]:5432/postgres"
Ce fichier ne doit jamais ĂȘtre commit (dĂ©jĂ dans.gitignorepar dĂ©faut) â il contient un mot de passe. -
Ăcris le schĂ©maDans
prisma/schema.prisma, sous les blocsgenerator/datasourcedĂ©jĂ prĂ©sents, ajoute :model Produit { id String @id @default(cuid()) nom String prix Int // en centimes, pour Ă©viter les erreurs d'arrondi stock Int @default(0) createdAt DateTime @default(now()) } model Commande { id String @id @default(cuid()) clientId String statut String @default("EN_ATTENTE") total Int createdAt DateTime @default(now()) lignes LigneCommande[] } model LigneCommande { id String @id @default(cuid()) commandeId String commande Commande @relation(fields: [commandeId], references: [id]) produitId String quantite Int prixUnitaire Int }Les prix sont stockĂ©s en centimes (entiers) plutĂŽt qu'en euros dĂ©cimaux â Ă©vite les erreurs d'arrondi classiques avec les nombres flottants. -
Applique la migration et vérifie
pnpm dlx prisma migrate dev --name init pnpm dlx prisma studio
migrate devcrĂ©e les tables et gĂ©nĂšre le client Prisma typĂ©.studioouvre une interface web locale pour voir/Ă©diter les donnĂ©es Ă la main.đ Comment voir le rĂ©sultat :prisma studioouvrelocalhost:5555â les tablesProduit,CommandeetLigneCommandedoivent apparaĂźtre dans la liste de gauche.
PiĂšge frĂ©quent : connexion refusĂ©e â vĂ©rifie qu'aucun caractĂšre spĂ©cial du mot de passe (@, #...) n'est mal encodĂ© dans l'URL. Supabase propose un bouton pour copier l'URL dĂ©jĂ encodĂ©e.
Authentification â Better Auth
Des comptes clients â historique de commandes, adresse â et une zone /dashboard protĂ©gĂ©e pour l'admin.
Prérequis : étape 2 validée (schéma Prisma en place).
-
Installe Better Auth
pnpm add better-auth
đ Comment voir le rĂ©sultat :better-authapparaĂźt danspackage.json. -
Crée la config serveur
// lib/auth/auth.ts import { betterAuth } from "better-auth"; import { prismaAdapter } from "better-auth/adapters/prisma"; import { prisma } from "@/lib/db/client"; export const auth = betterAuth({ database: prismaAdapter(prisma, { provider: "postgresql" }), emailAndPassword: { enabled: true }, });CrĂ©e aussilib/db/client.tsqui exporte une instance unique dePrismaClientâ Ă©vite d'en recrĂ©er une Ă chaque appel. -
Ajoute les tables auth au schéma
pnpm dlx @better-auth/cli generate pnpm dlx prisma migrate dev --name add_auth
Better Auth gĂ©nĂšre automatiquement les modĂšlesUser,Session,Accountdansschema.prisma.đ Comment voir le rĂ©sultat : ouvreprisma studioâ les tablesUser,Session,Accountdoivent apparaĂźtre. -
Ajoute le secret dans
.env# .env BETTER_AUTH_SECRET="génÚre une chaßne aléatoire longue" BETTER_AUTH_URL="http://localhost:3000"
-
Crée la route API
// app/api/auth/[...all]/route.ts import { auth } from "@/lib/auth/auth"; import { toNextJsHandler } from "better-auth/next-js"; export const { GET, POST } = toNextJsHandler(auth);đ Comment voir le rĂ©sultat : relancepnpm devet ouvre un endpoint Better Auth (ex.localhost:3000/api/auth/ok) â tu dois obtenir une rĂ©ponse JSON, pas une erreur 404. -
Crée le client auth et les pagesUn fichier
lib/auth/client.tsaveccreateAuthClient(), puis des pages/signupet/loginqui appellentauthClient.signUp.email(...)etauthClient.signIn.email(...).đ Comment voir le rĂ©sultat : crĂ©e un compte test surlocalhost:3000/signup, puis vĂ©rifie dans Prisma Studio qu'une ligne apparaĂźt dans la tableUser. -
ProtĂšge
/dashboardUnmiddleware.tsĂ la racine qui vĂ©rifie la session sur les routes/dashboard/*et redirige vers/loginsi absente.đ Comment voir le rĂ©sultat : en navigation privĂ©e (non connectĂ©), va surlocalhost:3000/dashboardâ tu dois ĂȘtre redirigĂ© vers/login.
PiĂšge frĂ©quent : si la doc officielle de Better Auth diffĂšre de ce qui est Ă©crit ici, suis la doc â c'est une librairie qui Ă©volue vite. Dis-le moi si un nom de fonction a changĂ©, on ajuste.
Paiement â Stripe
Encaisser un vrai paiement carte, en toute sécurité.
Prérequis : étape 3 validée.
-
CrĂ©e un compte Stripe (mode test)Sur stripe.com â le mode test permet de simuler des paiements sans vraie carte bancaire, avec le numĂ©ro
4242 4242 4242 4242. -
Installe le SDK
pnpm add stripe
đ Comment voir le rĂ©sultat :stripeapparaĂźt danspackage.json. -
Ajoute les clés dans
.env# .env STRIPE_SECRET_KEY="sk_test_..." STRIPE_WEBHOOK_SECRET="whsec_..."
Les deux se trouvent dans le tableau de bord Stripe, section Développeurs. -
Crée une session de paiement
// lib/stripe/checkout.ts "use server"; import Stripe from "stripe"; const stripe = new Stripe(process.env.STRIPE_SECRET_KEY); export async function createCheckoutSession(items) { const session = await stripe.checkout.sessions.create({ mode: "payment", line_items: items.map((i) => ({ price_data: { currency: "eur", product_data: { name: i.nom }, unit_amount: i.prix, }, quantity: i.quantite, })), success_url: `${process.env.BETTER_AUTH_URL}/commande/succes`, cancel_url: `${process.env.BETTER_AUTH_URL}/panier`, }); return session.url; }đ Comment voir le rĂ©sultat : se testera concrĂštement une fois la page panier branchĂ©e Ă l'Ă©tape 5 â pour l'instant, vĂ©rifie juste que le fichier ne contient pas d'erreur TypeScript dans ton Ă©diteur. -
Crée la route webhook
// app/api/stripe/webhook/route.ts // Vérifie la signature avec STRIPE_WEBHOOK_SECRET, // puis à l'événement "checkout.session.completed", // passe la Commande correspondante en statut PAYEE.
Ne marque jamais une commande payĂ©e depuis le navigateur (cĂŽtĂ© client) â seul le webhook, signĂ© par Stripe, fait foi. Sinon n'importe qui peut appeler ton API et se dĂ©clarer « payĂ© » sans payer.đ Comment voir le rĂ©sultat : lancestripe listen --forward-to localhost:3000/api/stripe/webhookdans un terminal sĂ©parĂ© â il doit afficherReady! Your webhook signing secret is whsec_.... Fais un paiement test (carte4242 4242 4242 4242) : ce terminal doit logguer l'Ă©vĂ©nementcheckout.session.completed.
PiĂšge frĂ©quent : en local, Stripe ne peut pas atteindre localhost pour envoyer le webhook â utilise stripe listen --forward-to localhost:3000/api/stripe/webhook (CLI Stripe) pendant le dĂ©veloppement.
Catalogue, panier & commandes
Parcourir les produits, les mettre au panier, passer commande.
Prérequis : étape 4 validée.
-
Page catalogue
app/produits/page.tsxâ liste les produits viaprisma.produit.findMany(), une carte par produit (shadcn/uiCard).đ Comment voir le rĂ©sultat : ouvrelocalhost:3000/produitsâ les produits que tu as ajoutĂ©s dans Prisma Studio doivent s'afficher, un par carte. -
Panier cÎté client
pnpm add zustand
Le panier vit dans le navigateur avant le paiement â pas besoin de base de donnĂ©es pour ça. Zustand garde l'Ă©tat du panier accessible depuis n'importe quel composant, sans tout faire remonter via les props. -
Page panier
app/panier/page.tsxâ rĂ©capitule les articles ajoutĂ©s, calcule le total, bouton « Payer » qui appellecreateCheckoutSession.đ Comment voir le rĂ©sultat : depuis le catalogue, ajoute 2-3 produits au panier puis ouvrelocalhost:3000/panierâ ils doivent y ĂȘtre listĂ©s avec le bon total (calcule-le Ă la main pour vĂ©rifier). -
Crée la commande avant le paiementCrée la
Commandeen base avec statutEN_ATTENTEjuste avant de rediriger vers Stripe â le webhook n'aura plus qu'Ă la faire passer ĂPAYEE.đ Comment voir le rĂ©sultat : clique sur « Payer » depuis le panier â juste avant la redirection vers Stripe, une nouvelle ligneEN_ATTENTEdoit apparaĂźtre dans la tableCommande(Prisma Studio).
Tests â Vitest & Playwright
Automatiser la vérification du parcours critique.
Prérequis : étapes 4 et 5 validées.
-
Installe et configure Vitest
pnpm add -D vitest
Ăcris un test danstests/panier.validation.test.tsqui vĂ©rifie quecalculTotalPaniercalcule correctement le total du panier avec plusieurs articles. -
Installe et configure Playwright
pnpm create playwright
RĂ©pond aux questions de l'installateur (TypeScript, dossiertests-e2e). Ăcris un test qui : crĂ©e un compte â ajoute un produit au panier â paie avec une carte de test Stripe â vĂ©rifie que la commande apparaĂźt en base. -
Lance les tests
pnpm exec vitest run pnpm exec playwright test
đ Comment voir le rĂ©sultat : le terminal affiche un rĂ©sumĂ© avec un nombre de tests « passed » en vert. Playwright peut aussi ouvrir un rapport HTML (pnpm exec playwright show-report) qui montre le parcours Ă©tape par Ă©tape, avec captures d'Ă©cran si un test Ă©choue.
DĂ©ploiement â Vercel
Une URL publique et fonctionnelle.
Prérequis : étape 6 validée.
-
Ajoute la génération Prisma au build
// package.json "scripts": { "postinstall": "prisma generate" }Sans ça, le build Vercel plante â le client Prisma doit ĂȘtre rĂ©gĂ©nĂ©rĂ© aprĂšs chaque install en production. -
Pousse le code sur GitHub
git remote add origin URL-DE-TON-DEPOT git push -u origin masterđ Comment voir le rĂ©sultat : rafraĂźchis la page du dĂ©pĂŽt sur GitHub â tes fichiers doivent y apparaĂźtre. -
Importe le projet sur VercelSur vercel.com â Add New â Project â sĂ©lectionne le dĂ©pĂŽt GitHub.đ Comment voir le rĂ©sultat : le tableau de bord Vercel passe de « Building » à « Ready », avec un lien de prĂ©visualisation cliquable.
-
Renseigne les variables d'environnementCopie
DATABASE_URL,BETTER_AUTH_SECRET,BETTER_AUTH_URL(URL Vercel finale),STRIPE_SECRET_KEY,STRIPE_WEBHOOK_SECRETdans Settings â Environment Variables.đ Comment voir le rĂ©sultat : pas d'effet visible immĂ©diatement â redĂ©ploie (« Redeploy ») puis teste Ă l'Ă©tape suivante. -
Configure le webhook Stripe en productionDans le tableau de bord Stripe : ajoute un endpoint pointant vers
https://tondomaine.vercel.app/api/stripe/webhookâ l'URL locale utilisĂ©e avec la CLI ne fonctionne plus une fois dĂ©ployĂ©.đ Comment voir le rĂ©sultat : dans le tableau de bord Stripe, section Webhooks, l'endpoint doit afficher un statut vert « Enabled ». -
DĂ©ploie et vĂ©rifie en ligneOuvre l'URL fournie par Vercel, refais le parcours critique Ă la main : crĂ©er un compte â ajouter un produit au panier â payer avec une carte de test â vĂ©rifier la commande.đ Comment voir le rĂ©sultat : sur l'URL
*.vercel.app, un paiement test complet doit faire passer la commande enPAYEEâ vĂ©rifiable dans Prisma Studio ou directement dans Supabase.