Aller au contenu
siavash izadi (Accueil)
Tous les projets
En ligne

NEXORA

Boutique e-commerce complète pour une marque fictive : catalogue, panier, paiement Stripe, comptes et back-office, avec un stock qui ne peut pas être survendu.

Année
2026
Rôle
Conception, développement, tests, déploiement et documentation. Projet réalisé seul.
Technologies
  • Next.js 16
  • TypeScript
  • PostgreSQL
  • Prisma
  • Stripe
  • better-auth
  • Vitest
  • Playwright
  • Docker
Page d’accueil de NEXORA : casque Halo One rendu en 3D, prix et caractéristiques.

Contexte

Le problème

Une boutique en ligne paraît simple jusqu’aux cas réels : deux clients qui achètent la dernière unité au même moment, un paiement confirmé deux fois, un prix modifié dans le navigateur. Je voulais un e-commerce qui résiste à ces cas, et le prouver par des tests.

Pour qui

Recruteurs et responsables techniques qui évaluent des compétences back-end, base de données et sécurité, au-delà de l’interface.

Architecture

  • Monolithe modulaire Next.js 16 (App Router, Server Components, Server Actions) : les routes appellent des services de domaine, seuls ces services accèdent à la base.
  • PostgreSQL 16 avec Prisma 7, et des contraintes CHECK écrites à la main pour que la base refuse elle-même un total incohérent.
  • Paiement par Stripe Checkout ; seul le webhook signé et idempotent peut marquer une commande comme payée.
  • Authentification better-auth avec sessions en base ; le rôle n’est jamais lu depuis une entrée utilisateur.
  • Image Docker sans privilèges root, en lecture seule, avec Postgres et un service de migration dédié ; déployée sur mon serveur derrière Nginx.

Décisions et compromis

Les montants en centimes entiers

Aucun nombre à virgule pour l’argent. Chaque commande garde une copie des prix, des noms et de l’adresse au moment de l’achat : modifier un produit ne réécrit jamais une commande passée.

Un stock réservé par une seule requête SQL

La réservation est un UPDATE conditionnel (« seulement si le stock suffit »), exécuté par la base de façon atomique. Un test lance 8 acheteurs simultanés sur 3 unités : 3 commandes passent, 5 sont refusées.

Le webhook, seule source de vérité du paiement

Le retour du navigateur après paiement ne prouve rien. La commande n’est marquée payée que par l’événement Stripe vérifié, traité une seule fois même s’il arrive plusieurs fois.

Difficultés rencontrées

Problème
Il fallait des images de produits sans montrer les produits d’autres marques sous le nom NEXORA, ce que font les photos de banque d’images.
Solution
Les images sont des rendus 3D de modèles procéduraux écrits avec three.js d’après les caractéristiques du catalogue, signalés comme rendus sur le site.
Problème
Le moteur de Prisma ne pouvait pas être téléchargé dans l’environnement où les migrations ont été préparées.
Solution
Les migrations SQL ont été écrites et vérifiées autrement, et la CI contrôle qu’elles correspondent exactement au schéma (détection de dérive).

État du projet

En place

  • 79 tests unitaires et d’intégration : prix, codes promo, panier, commandes, concurrence, webhooks, droits d’accès.
  • 20 tests de bout en bout sur le build de production, dont un achat entièrement au clavier, des tests d’IDOR et de redirection ouverte, et des contrôles d’accessibilité axe.
  • Back-office : machine à états des commandes, ajustements de stock atomiques, codes promo, modération des avis, journal d’audit.
  • CSP, en-têtes de sécurité, limites de débit, validation de toutes les entrées côté serveur.
  • Sauvegarde nocturne de la base, avec restauration testée.

Prévu, pas encore fait

  • Envoi d’e-mails : vérification d’adresse, réinitialisation du mot de passe en production, confirmations de commande.
  • Remboursements exécutés par l’API Stripe (aujourd’hui seulement enregistrés).

Limites connues

  • Les paiements fonctionnent en mode test Stripe : aucune commande n’est réellement payée ni expédiée.
  • Les images de produits sont des rendus 3D, pas des photographies.
  • Une page de produit inexistante affiche la page 404 avec le code HTTP 200 (et noindex).
  • La limite de débit est gardée par processus : suffisant pour un seul conteneur.

Captures d’écran

Page produit NEXORA : galerie, choix de variante, stock et prix.
Page produit : variante synchronisée avec l’URL, stock en direct, galerie au clavier.
Liste des produits NEXORA avec filtres par catégorie, prix et stock.
Catalogue : filtres, tri et pagination dans l’URL.
Panier NEXORA avec code promo et progression vers la livraison gratuite.
Panier : quantités limitées par le stock, codes promo validés côté serveur.
Tableau de bord d’administration NEXORA : commandes et indicateurs.
Back-office : commandes, produits, stock, codes promo, avis et journal d’audit.