Backoffice
Un outil interne pour gĂ©rer des donnĂ©es â exemple : un catalogue produits. Base de donnĂ©es, CRUD, accĂšs protĂ©gĂ© si besoin.
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 Ă ce modĂšle « catalogue produits » â remplace
Produit par tes propres données (clients, articles, stock...).
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 (logo, liens « Docs », « Deploy »). Le terminal afficheReadyet n'affiche pas d'erreur rouge.
Base de donnĂ©es â Prisma + Supabase
Une base PostgreSQL en ligne, avec une table Produit créée 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 d'initialisation).
-
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 quantite Int @default(0) prix Float categorie String? updatedAt DateTime @updatedAt }Remplace par les champs de tes propres donnĂ©es â un backoffice de clients, d'articles, de commandes suivra exactement le mĂȘme schĂ©ma de raisonnement. -
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:5555dans ton navigateur â la tableProduitdoit apparaĂźtre dans la liste de gauche, vide mais avec ses colonnes (nom, quantite, prix...).
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
S'inscrire, se connecter, et protéger /dashboard des visiteurs non connectés.
Prérequis : étape 2 validée (schéma Prisma en place). Si l'outil est utilisé par toute l'équipe sans distinction d'accÚs, tu peux sauter cette étape.
-
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 maintenant apparaĂźtre dans la liste. -
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 ouvrelocalhost:3000/api/auth/ok(ou tout endpoint Better Auth valide) â 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 : ouvrelocalhost:3000/signup, crĂ©e un compte test. Puis ouvreprisma studioâ une ligne doit apparaĂźtre 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 : ouvre un navigateur en navigation privĂ©e (pas connectĂ©) et va surlocalhost:3000/dashboardâ tu dois ĂȘtre redirigĂ© vers/login, pas voir le contenu du dashboard.
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.
CRUD Produits
Créer, lister, modifier et supprimer un produit depuis /dashboard.
Prérequis : étape 3 validée (ou étape 2 si tu as sauté l'authentification).
-
Ajoute des composants shadcn/ui
pnpm dlx shadcn@latest add button input table
đ Comment voir le rĂ©sultat :ls components/uiâbutton.tsx,input.tsx,table.tsxdoivent apparaĂźtre. -
Valide les entrées avec Zod
// lib/validations/produit.ts import { z } from "zod"; export const produitSchema = z.object({ nom: z.string().min(1).max(80), quantite: z.number().int().min(0), prix: z.number().positive(), categorie: z.string().optional(), });đ Comment voir le rĂ©sultat : pas d'effet visible seul â ce schĂ©ma sera testĂ© concrĂštement Ă l'Ă©tape suivante, en soumettant un formulaire invalide. -
Ăcris les Server Actions
// app/dashboard/produits/actions.ts "use server"; // createProduit(formData): valide avec produitSchema, prisma.produit.create(...) // updateProduit(id, formData): idem, prisma.produit.update(...) // deleteProduit(id): prisma.produit.delete(...)
Si tu as activĂ© Better Auth, vĂ©rifie la session avant chaque Ă©criture â sinon n'importe qui avec l'URL peut modifier les donnĂ©es. -
Construis la page
/dashboard/produitsUn tableau (prisma.produit.findMany()), un formulaire d'ajout, un bouton modifier/supprimer par ligne.đ Comment voir le rĂ©sultat : ouvrelocalhost:3000/dashboard/produits, ajoute un produit test via le formulaire â il doit apparaĂźtre dans le tableau sans recharger la page manuellement. VĂ©rifie aussi dans Prisma Studio que la ligne existe bien en base.
DĂ©ploiement â Vercel
Une URL publique et fonctionnelle.
Prérequis : étape 4 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(mets l'URL Vercel finale) dans Settings â Environment Variables.đ Comment voir le rĂ©sultat : pas d'effet visible immĂ©diatement â redĂ©ploie (« Redeploy ») puis teste la connexion en production Ă l'Ă©tape suivante. -
DĂ©ploie et vĂ©rifie en ligneOuvre l'URL fournie par Vercel, refais le parcours critique Ă la main : crĂ©er un produit, le modifier, le supprimer.đ Comment voir le rĂ©sultat : sur l'URL
*.vercel.app, connecte-toi, ajoute un produit â il doit apparaĂźtre dans le tableau exactement comme en local.