Tirage instantané pondéré
Un lot attribué immédiatement à chaque participant, réparti par quotas journaliers.

2026
Grand’Mère · Jacobs Douwe Egberts · Développement full-stack (Next.js) pour l’agence Clutch · App Next.js + admin, tirage pondéré, Supabase
Pour la fête des grands-mères 2026, l’agence Clutch (vidéo et affichage pour grandes marques) m’a confié le développement du jeu-concours en ligne de Café Grand’Mère, propriété de Jacobs Douwe Egberts.
Chaque visiteur remplit un formulaire, reçoit immédiatement un lot (bon Lalalab 40 €, lot tasses et café, ou bon de réduction 1 €) via un tirage instantané pondéré, puis est inscrit au tirage final de 4 week-ends. Un back-office suit les volumes, exporte les participants et déclenche le tirage final.
Deux semaines de développement pour tenir le calendrier de lancement, sur une campagne courte et bornée dans le temps. Résultat : environ 26 000 participants.
Un lot attribué immédiatement à chaque participant, réparti par quotas journaliers.
Email unique en base, Cloudflare Turnstile contre les bots, validation d’adresse via la BAN.
Stats, export CSV, déclenchement du tirage final des 4 week-ends, sans intervention développeur.
Développé et livré en deux semaines pour tenir la date de lancement de la campagne.
Admin
Statistiques, export CSV des participants, déclenchement du tirage final, protégé par JWT.
Fiabilité
Quotas du jour pré-calculés à minuit, avec un filet de sécurité si le cron rate son exécution.
Formulaire
Turnstile, autocomplete d’adresse via la BAN, validation Zod, réponse immédiate avec le lot gagné.
Confirmation
Page de confirmation en Server Component, contenu différent selon Lalalab, tasses ou bon d’un euro.
Sous le capot
App Next.js 16 monolithique (App Router, React 19, TypeScript strict), sans backend séparé : Supabase pour les données, Resend pour les emails, Cloudflare Turnstile contre les bots, JWT pour l’admin. Deux univers visuels isolés, le site public à la charte Grand’Mère et l’admin en shadcn/ui, sans CSS partagé entre les deux.
Tirage
Chaque participant repart avec un lot immédiat, réparti par quotas journaliers et pondération, pas au hasard pur.
Supabase
Un champ écrit par l’API mais absent du script SQL initial, corrigé directement en base pour ne pas casser les inscriptions.
Cron
Les quotas du jour sont pré-calculés à minuit par un cron Vercel, avec un repli si le cron ne s’exécute pas.
Next.js
Le site public et l’admin ne partagent aucun CSS global, pour isoler deux chartes graphiques complètement différentes.
RGPD
Les données personnelles ne sont pas chiffrées côté application, une contrainte documentée à traiter au niveau de Supabase.
01 / 05
Problème
Distribuer 25 bons Lalalab, 150 lots tasses et des milliers de bons d’un euro sur deux mois, sans épuiser un lot rare le premier jour ni laisser le stock invendu à la fin.
Approche
Les quotas du jour sont calculés s’ils n’existent pas encore : le stock restant divisé par les jours restants jusqu’à la fin de campagne, arrondi au supérieur. Un lot n’est éligible au tirage que si son quota du jour et son stock global sont tous les deux positifs. Le tirage lui-même est pondéré, pas proportionnel aux quotas : Lalalab pèse pour environ 0,5 % des tirages, les tasses pour 3 %, le bon d’un euro pour plus de 96 %. Chaque tirage gagnant décrémente le quota et le stock, puis génère un code unique. Si la boucle ne retombe sur aucun lot, un bon d’un euro est attribué par défaut plutôt que de faire échouer l’inscription.
Tirage pondéré à quotas
02 / 05
Problème
Un écart entre le code applicatif et le schéma SQL versionné : le champ moment_type était utilisé par l’API de participation sans exister dans le SQL de création des tables.
Approche
La colonne a été ajoutée directement en base pour débloquer les inscriptions, le temps de mettre à jour le script SQL versionné en parallèle. Un rappel utile sur ce genre de campagne à calendrier serré : le schéma documenté et la base réelle peuvent diverger localement le temps d’un correctif, tant que c’est tracé et corrigé rapidement plutôt que découvert en production sans explication.
Une colonne ajoutée à la main
03 / 05
Problème
Garantir que les quotas du jour existent au moment où le premier visiteur participe, même si le cron quotidien échoue ou prend du retard.
Approche
Un cron Vercel protégé par un secret Bearer pré-alloue les quotas du jour à minuit UTC. Si ce cron rate son exécution, ce n’est pas bloquant : le premier tirage de la journée crée les quotas à la volée s’ils n’existent pas encore. Cette redondance évite un point de défaillance unique sur un mécanisme qui conditionne l’attribution de chaque lot pendant deux mois.
Cron avec filet de sécurité
04 / 05
Problème
Faire cohabiter la charte Grand’Mère (rouge, pêche, cœurs, maquette Figma) et un dashboard shadcn/ui classique, sans que l’un ne pollue le style de l’autre.
Approche
Le layout racine Next.js ne charge aucun CSS global. Chaque univers, le site concours d’un côté et le dashboard admin de l’autre, charge sa propre feuille de styles. Résultat : la charte de la marque reste intacte sur le site public, pendant que l’admin garde une interface neutre et lisible pour piloter la campagne, sans se soucier des cœurs et du rouge Grand’Mère.
Deux univers visuels, un seul layout racine
05 / 05
Problème
Livrer une app de collecte de données personnelles en deux semaines, avec une politique de conservation et de chiffrement qui reste à finaliser côté infrastructure.
Approche
La validation, l’unicité de l’email et l’authentification admin sont en place (Zod, JWT httpOnly, secret cron). En revanche, les données personnelles ne sont pas chiffrées applicativement : elles restent en clair dans PostgreSQL. Ce point est documenté comme un chantier à traiter côté Supabase, durée de conservation et RLS notamment, plutôt que comme un détail oublié. Sur une campagne à durée limitée, distinguer ce qui est fait de ce qui reste à faire évite les mauvaises surprises après le lancement.
RGPD : un chantier identifié, pas ignoré
Décisions
Par un tirage pondéré immédiat, dans la limite des quotas du jour : environ 0,5 % de chance sur les bons Lalalab, 3 % sur les lots tasses, le reste en bons d’un euro.
Projets

2026
Boutique Shopify Plus pour Näak, marque de nutrition et d’hydratation ultra-trail partenaire de l’UTMB® World Series. Refonte produit, abonnements et déploiement multi-marchés.

2026
Thème Shopify OS 2.0 écrit from scratch pour Slicy, protections et stickers vélo sur-mesure : configurateur de matching et personnalisation SVG en direct.

2026
Migration WooCommerce vers Shopify pour GoodBro, animalerie en ligne : 760 produits, 37 130 commandes, 1 177 abonnements, zéro email client.
Suite
Formulaire, tirage, back-office : une app livrée dans le calendrier d’une campagne, pas dans celui d’un projet web classique.