Paquets de café Grand’Mère personnalisables

2026

Café Grand’Mère

Voir le site →

Grand’Mère · Jacobs Douwe Egberts · Développement full-stack (Next.js) pour l’agence Clutch · App Next.js + admin, tirage pondéré, Supabase

Contexte

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.

Objectifs & livrables

Tirage instantané pondéré

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

Unicité et anti-fraude

Email unique en base, Cloudflare Turnstile contre les bots, validation d’adresse via la BAN.

Back-office de pilotage

Stats, export CSV, déclenchement du tirage final des 4 week-ends, sans intervention développeur.

Calendrier de campagne

Développé et livré en deux semaines pour tenir la date de lancement de la campagne.

Admin

Pilotage sans développeur

Statistiques, export CSV des participants, déclenchement du tirage final, protégé par JWT.

Fiabilité

Cron de pré-allocation

Quotas du jour pré-calculés à minuit, avec un filet de sécurité si le cron rate son exécution.

Formulaire

Participation en une page

Turnstile, autocomplete d’adresse via la BAN, validation Zod, réponse immédiate avec le lot gagné.

Confirmation

Gain personnalisé par lot

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.

TirageQuotas

01 / 05

Tirage pondéré à quotas

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

SupabaseSQL

02 / 05

Une colonne ajoutée à la main

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

CronFiabilité

03 / 05

Cron avec filet de sécurité

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é

Next.jsArchitecture

04 / 05

Deux univers visuels, un seul layout racine

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

RGPDSécurité

05 / 05

RGPD : un chantier identifié, pas ignoré

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

Pourquoi ces choix techniques

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.

Suite

Un jeu-concours ou une campagne à développer ?

Formulaire, tirage, back-office : une app livrée dans le calendrier d’une campagne, pas dans celui d’un projet web classique.