Étude de cas · Freelance, client réel

Lune-Soleil : une boutique e-commerce sur mesure en Next.js, du stock au paiement

Une créatrice de bijoux du Béarn vend ses pièces en ligne et sur les marchés, souvent en exemplaire unique. J'ai développé seul sa boutique, du catalogue à la facture, avec un stock commun aux deux canaux.

La boutique Lune-Soleil affichée sur un ordinateur portable et un smartphone

En bref

Produit
Boutique en ligne sur mesure de bijoux artisanaux faits main, sur lune-soleil.fr
Mon rôle
Développeur freelance, seul sur le projet : conception, développement, tests, déploiement et maintenance
Dates
En production depuis le 9 septembre 2026, paiements réels depuis le 24 octobre, ouverture au public le 1er novembre 2026
Stack
Next.js 16, React 19, TypeScript strict, PostgreSQL 18, Prisma 7, Better Auth, Stripe Checkout, Docker, VPS OVHcloud
Code
Dépôt public : github.com/krismos64/lune-soleil
Statut
Boutique ouverte et maintenue : corrections, sécurité et demandes de la cliente

Le besoin

La créatrice vend la même pièce sur internet et sur un stand de marché. Beaucoup de bijoux existent en un seul exemplaire : si une pièce part au marché, elle ne doit plus pouvoir être payée en ligne, et inversement. Elle gère aussi la boutique seule, souvent depuis son téléphone, y compris derrière son stand.

Ce que fait la boutique

L'architecture

L'application est un monolithe modulaire, pour une seule boutique, en France et en euros. Les gestionnaires de route et les Server Actions de Next.js servent d'adaptateurs d'entrée et ne portent aucune règle métier. Les cas d'usage vivent dans une couche de services, l'accès aux données dans des dépôts par domaine, et les services externes (Stripe, Sendcloud, emails) sont isolés derrière leurs propres modules.

Quatre règles qui protègent l'argent et le stock

1. Le dernier exemplaire ne se vend qu'une fois

C'est le point le plus critique de la boutique. Lire le stock puis l'écrire laisserait passer deux réservations simultanées de la même pièce. La réservation se fait donc en une seule instruction SQL atomique, avec la condition de stock dans le WHERE. Le test de concurrence qui le prouve a été écrit avant le paiement et tourne en intégration continue.

  1. Une cliente valide son panier en ligne pendant que la créatrice vend la même pièce sur son stand.
  2. Les deux demandes de réservation arrivent à la base au même moment.
  3. La réservation est une seule instruction SQL : elle ne retire une unité que si la condition quantite >= 1, placée dans le WHERE, est encore vraie.
  4. La première demande modifie une ligne et réserve la pièce. La seconde ne modifie rien et reçoit « déjà vendue ». Lire le stock puis l'écrire en deux temps aurait laissé passer les deux.

Requête simplifiée pour le schéma.

2. Seul Stripe confirme un paiement

Le retour du navigateur après paiement ne prouve rien : seul un événement signé envoyé par Stripe au serveur confirme une commande. L'idempotence est ancrée sur l'effet (la commande déjà payée) et non sur l'identifiant de l'événement, qui laisserait passer le croisement entre un webhook et une réconciliation.

3. Une facture émise ne change plus

Une ligne de commande et une facture émise sont immuables. Une correction produit un avoir. Le numéro de facture est attribué dans la transaction qui crée le document, ce qui évite les trous et les doublons de numérotation.

4. Aucun nombre à virgule dans les montants

Tous les montants sont stockés en centimes entiers. Aucun flottant n'entre dans un calcul monétaire, ce qui écarte les erreurs d'arrondi sur les totaux, les remises et les remboursements.

Infrastructure et déploiement

La boutique tourne sur un VPS OVHcloud avec Docker Compose derrière Nginx. GitHub Actions construit l'image de l'application en intégration continue et la tague par le SHA du commit, ce qui permet de savoir exactement quelle version tourne en production.

Un développement encadré par des garde-fous

J'ai développé Lune-Soleil avec un agent de code, Claude Code, encadré par des hooks, un skill de processus et un sous-agent de relecture. Les tests sont eux-mêmes vérifiés par mutation : on casse volontairement le code pour s'assurer qu'un test échoue. La série ci-dessous détaille cette configuration.

Où en est la boutique

La boutique est en production depuis septembre 2026 et ouverte au public depuis le 1er novembre. Je la maintiens : corrections, mises à jour de sécurité et demandes de la cliente. Elle vient d'ouvrir, je ne publie donc aucun résultat commercial.

Encadrer un agent de code sur ce projet : la série

  1. Pourquoi j'encadre mon agent de code
  2. Hooks Claude Code : où placer un garde-fou
  3. Skills et sous-agents : déléguer le processus
  4. La preuve par mutation : vérifier que les tests servent