E-book pratique · édition 2026

Construis ta propre plateforme de tickets Wi-Fi avec Claude Code

Du nom de ta zone jusqu'au premier ticket vendu en Mobile Money : identité visuelle, outils, prompts prêts à copier, base de données, paiement, hébergement et routeur MikroTik. Chaque étape se coche ; ta progression reste enregistrée dans ce navigateur.

Niveau débutant motivé, aucun code à écrire soi-même Durée 3 à 7 jours selon les validations Modèle basé sur la plateforme Fô-Zône en production
00

Ce que tu vas construire

Le fonctionnement complet, avant de toucher à quoi que ce soit.

Une Wi-Fi Zone vend l'accès internet par tickets : un identifiant et un mot de passe valables une durée donnée (1 h, 24 h, 7 jours…). Aujourd'hui beaucoup de gérants vendent ces tickets à la main, en papier. Ta plateforme automatise tout : le client paie en Mobile Money depuis son téléphone et reçoit son ticket en quelques secondes, sans que tu sois là.

Le parcours d'un client

Il se connecte au Wi-FiLe routeur MikroTik affiche ta page de connexion (portail captif).
Il clique « Acheter »Il arrive sur ta page d'achat, choisit un tarif, saisit son numéro.
Il paieMoneroo affiche MTN, Moov, Orange, Wave… selon le pays. Il valide sur son téléphone.
Moneroo prévient ton serveurUn webhook signé confirme le paiement à ton API.
Le ticket est attribuéTon serveur réserve un ticket libre du bon tarif, en une seule opération.
Il se connecteSon identifiant s'affiche ; il le saisit sur le portail. Internet est ouvert.

Les briques du système

BriqueRôleOutil utilisé
FrontendPage d'accueil, page d'achat, tableau de bord du gérantReact + Vite + Tailwind, hébergé sur Vercel
Backend (API)Paiements, attribution des tickets, comptabilité, sécuritéNode.js + Express, hébergé sur Render
Base de donnéesZones, tarifs, tickets, paiements, retraitsSupabase (PostgreSQL)
Agrégateur de paiementEncaisse le Mobile Money dans 6 paysMoneroo
RouteurDiffuse le Wi-Fi, bloque l'accès tant que le client n'a pas de ticketMikroTik (Hotspot)
DéveloppeurÉcrit tout le code à partir de tes instructionsClaude Code dans VS Code

Les fonctionnalités finales

  • Plusieurs zones Wi-Fi par compte, chacune avec son pays, son routeur et son numéro de gérant.
  • Tarifs par zone (nom, prix, durée). Un tarif déjà vendu peut être supprimé sans casser l'historique.
  • Import de tickets par fichier CSV, avec statuts libre / vendu / expiré et alerte de stock bas.
  • Paiement Mobile Money multi-pays : Bénin, Côte d'Ivoire, Togo, Sénégal, Mali, Burkina Faso.
  • Attribution atomique : impossible de vendre deux fois le même ticket, même avec 50 achats simultanés.
  • Retrouver son ticket avec le numéro de téléphone utilisé pour payer.
  • Comptabilité : chiffre d'affaires brut et net, ventes par jour, répartition par opérateur, export CSV.
  • Générateur de portail captif : le gérant télécharge ses pages MikroTik déjà personnalisées.
  • Option plateforme : ouvrir ton système à d'autres gérants, prendre une commission, gérer leurs retraits.
01

Prérequis et budget

Ce qu'il te faut avant de commencer.

Matériel

  • Un ordinateur Windows 10/11 ou Mac, 8 Go de RAM minimum, connexion internet stable.
  • Un routeur MikroTik (hAP ax lite, hAP ac², hEX + point d'accès…) avec RouterOS 7.
  • Une source internet pour la zone : Starlink, fibre, 4G/5G.
  • Un téléphone avec un compte Mobile Money pour tester un vrai paiement.

Comptes à ouvrir

ServicePour quoiCoût indicatif
Nom de domaine (Namecheap, Hostinger, OVH…)L'adresse de ta plateforme, ex. 8 à 15 $ / an
Claude (plan Pro ou Max)Claude Code, ton développeurPro ≈ 20 $ / mois
GitHubStocker ton code, relier Vercel et RenderGratuit
SupabaseBase de donnéesGratuit pour démarrer
VercelHéberger le frontendHobby gratuit · Pro ≈ 20 $ / mois
RenderHéberger l'APIStarter ≈ 7 $ / mois
MonerooEncaisser le Mobile MoneyCommission par transaction

Prix indicatifs relevés en 2026 : vérifie sur chaque site avant de payer.

À savoirLe plan gratuit de Render met le serveur en veille après quelques minutes sans visite. Le premier paiement qui arrive doit alors attendre son réveil (près d'une minute), et le client croit que ça n'a pas marché. Pour une zone qui vend vraiment, prends le plan payant dès la mise en ligne. Le plan Hobby de Vercel est réservé à un usage non commercial : passe en Pro quand tu encaisses.

Checklist du chapitre

02

Nom, logo et charte graphique

L'identité de ta zone. Tout le reste en découle.

Choisir le nom

  • Court (2 syllabes idéalement), facile à dire au téléphone et à taper sur un clavier mobile.
  • Le nom de domaine en .com, .org, .net ou ton extension pays (.bj, .ci…) doit être libre. Vérifie-le avant de t'attacher au nom.
  • Pas d'accents ni de tirets dans le domaine : « Fô-Zône » devient fozone.org.
  • Vérifie que le nom n'est pas déjà une marque connue dans ton pays.

Le logo

Il te faut trois fichiers : le logo complet (symbole + nom), le symbole seul en carré (pour l'icône d'onglet et l'écran du téléphone), et une version blanche pour les fonds sombres. Format idéal : SVG, sinon PNG 1024 × 1024 sur fond transparent.

  • Avec un graphiste : compte 15 000 à 50 000 F CFA. Demande les fichiers sources.
  • Avec Claude : Claude peut dessiner un logo simple en SVG. Utilise le prompt ci-dessous sur claude.ai.
  • Avec Canva : rapide, mais exporte en SVG ou PNG transparent.

La fiche de ton projet

Remplis ces champs. Tous les prompts et commandes de l'e-book se mettent à jour avec tes valeurs, et la fiche reste enregistrée dans ce navigateur.

Aperçu de ta palette

Les valeurs par défaut sont celles de Fô-Zône, à titre d'exemple.

Prompt : créer le logo avec Claude

Sur claude.ai, dans une nouvelle conversation :

Prompt · claude.ai
Je lance « {{NOM}} », une plateforme de vente de tickets Wi-Fi payés en Mobile Money ({{PAYS}}). Ambiance : {{STYLE}}. Couleurs : {{C1}} (principale) et {{C2}} (secondaire).

Propose-moi 4 pistes de logo, chacune en SVG autonome (viewBox 0 0 512 512, pas de police externe, formes vectorisées) :
1. un symbole seul, lisible à 32 px (icône d'onglet) ;
2. le symbole + le nom « {{NOM}} » à côté.
Évite les clichés (ondes Wi-Fi génériques seules, globe). Pour chaque piste, explique l'idée en une phrase.
Quand j'aurai choisi, donne-moi aussi la version blanche sur fond transparent.

La charte en une page

Avant le code, fige ces décisions. Claude s'en servira pour la maquette.

  • 2 couleurs de marque (codes hexadécimaux) + un gris foncé pour le texte.
  • 2 polices Google Fonts : une pour les titres, une pour le texte. Exemples sûrs : Poppins / Inter, Sora / Nunito Sans, Outfit / DM Sans.
  • Le ton : tutoiement ou vouvoiement des clients, phrases courtes.
  • Thème sombre : oui ou non (Fô-Zône propose les deux avec une bascule).

Checklist du chapitre

03

Acheter le nom de domaine

À faire maintenant : la configuration DNS viendra au chapitre 11.

  1. Va sur un registraire : Namecheap, Hostinger ou OVH.
  2. Cherche . S'il est pris, essaie une autre extension ou une variante courte.
  3. Achète-le pour 1 an minimum. Active le renouvellement automatique : un domaine expiré coupe ta plateforme et les paiements.
  4. Refuse les options d'hébergement et d'e-mail proposées au panier : tu n'en as pas besoin.
  5. Garde l'onglet « DNS » ou « Gestion DNS » de ton registraire : tu y reviendras.
Plan d'adressesTa plateforme utilisera deux adresses : pour le site (Vercel) et pour l'API (Render). Un seul domaine suffit, le sous-domaine api est gratuit.

Checklist du chapitre

04

S'abonner à Claude

Claude Code est inclus dans les plans payants de Claude.

  1. Va sur claude.ai et crée un compte avec l'e-mail du projet.
  2. Ouvre Paramètres → Abonnement (ou clique « Upgrade »).
  3. Choisis Pro pour commencer. Si tu atteins souvent la limite d'utilisation pendant le développement, passe à Max.
  4. Paie par carte bancaire (Visa/Mastercard, carte prépayée ou virtuelle acceptée selon ta banque).
ConseilLes limites d'utilisation se réinitialisent toutes les quelques heures. Si Claude te dit que la limite est atteinte, fais une pause : il reprendra exactement là où il s'était arrêté, car tout est dans tes fichiers et dans Git.

Checklist du chapitre

05

Installer VS Code et Claude Code

Quatre logiciels, une seule fois.

1. Node.js

Le moteur qui fait tourner ton API et construit ton site. Télécharge la version LTS sur nodejs.org, puis installe en laissant les options par défaut.

2. Git

Il garde l'historique de chaque modification et permet de revenir en arrière si Claude casse quelque chose. Windows : git-scm.com/download/win, options par défaut. Mac : il est proposé automatiquement à la première utilisation.

3. Visual Studio Code

Ton éditeur. Télécharge-le sur code.visualstudio.com. Pendant l'installation Windows, coche « Ajouter l'action Ouvrir avec Code » et « Ajouter à PATH ».

4. L'extension Claude Code

  1. Ouvre VS Code, clique sur l'icône Extensions dans la barre de gauche (ou Ctrl+Shift+X).
  2. Cherche Claude Code, vérifie que l'éditeur est Anthropic, clique Installer.
  3. Une icône Claude apparaît en haut à droite de l'éditeur ou dans la barre latérale. Clique dessus.
  4. Choisis « Se connecter avec un compte Claude ». Le navigateur s'ouvre : autorise l'accès, reviens dans VS Code.

Vérifier que tout est en place

Dans VS Code, ouvre un terminal : menu Terminal → Nouveau terminal. Tape ces commandes une par une ; chacune doit afficher un numéro de version.

Terminal
node -v
npm -v
git --version

Configure ensuite ton identité Git (une seule fois) :

Terminal
git config --global user.name "Ton Nom"
git config --global user.email "ton-email@exemple.com"
AlternativeClaude Code existe aussi en ligne de commande et dans l'application de bureau Claude. L'e-book utilise l'extension VS Code : tu vois les fichiers changer à côté de la conversation, et tu valides chaque modification.

Réglages utiles de l'extension

  • Mode de permissions : au début, laisse Claude demander avant chaque commande. Quand tu es à l'aise, autorise les commandes courantes (npm install, git commit).
  • Mode plan : pour les grosses étapes, demande d'abord un plan (bouton ou Shift+Tab selon la version). Claude propose, tu valides, puis il code.
  • Références de fichiers : tape @ puis un nom de fichier pour montrer un fichier précis à Claude.

Checklist du chapitre

06

Créer le dossier du projet

Un dossier vide, ouvert dans VS Code, avec ton logo dedans.

  1. Crée un dossier Projets à un endroit simple, par exemple D:\Projets (évite les chemins avec espaces ou accents).
  2. Dedans, crée le dossier .
  3. Dans ce dossier, crée un sous-dossier brand et copie-y ton logo : logo.svg, logo-icon.svg, logo-white.svg.
  4. Dans VS Code : Fichier → Ouvrir le dossier… et choisis . Accepte « Faire confiance aux auteurs ».
  5. Ouvre le panneau Claude Code. Tu es prêt à envoyer le premier prompt.

Ou, depuis le terminal :

Terminal
mkdir D:\Projets\{{DOSSIER}}
cd D:\Projets\{{DOSSIER}}
mkdir brand
code .
Ne lance pas git init toi-mêmeLe premier prompt demande à Claude de le faire, avec le bon fichier .gitignore dès le départ. C'est ce fichier qui empêche tes clés secrètes de partir un jour sur GitHub.

Checklist du chapitre

07

Le prompt de départ

Il pose le cadre de tout le projet. Copie-le tel quel dans Claude Code.

Ce prompt décrit le produit, impose la technique, fixe les règles de travail et lance seulement la phase 1 : la maquette. Claude s'arrête ensuite et attend ta validation. Ce découpage par phases est la clé : tu vérifies à chaque étape au lieu de découvrir 50 problèmes à la fin.

Prompt n°1 · Claude Code
Tu es le développeur principal de « {{NOM}} », une plateforme de vente automatisée de tickets Wi-Fi payés en Mobile Money, reliée à des routeurs MikroTik (hotspot). Je ne suis pas développeur : explique simplement, et dis-moi toujours comment tester ce que tu as fait.

# Le produit
- Un gérant crée ses zones Wi-Fi (nom, pays, adresse, IP ou nom d'hôte du routeur, numéro du gérant, position GPS facultative).
- Pour chaque zone, il crée des tarifs (nom, prix en F CFA, durée en heures) et importe ses tickets MikroTik (identifiant + mot de passe + profil) par fichier CSV.
- Le client connecté au Wi-Fi ouvre la page d'achat de la zone, choisit un tarif, saisit son numéro, paie en Mobile Money via l'agrégateur Moneroo, et reçoit immédiatement un ticket du tarif payé.
- Le client peut retrouver un ticket déjà acheté avec son numéro de téléphone.
- Le gérant a un tableau de bord : ventes du jour, chiffre d'affaires brut et net de commission, tickets restants, alertes de stock bas, comptabilité par jour et par opérateur, export CSV.
- Le gérant génère depuis le tableau de bord ses pages de portail captif MikroTik (login.html, redirect.html) personnalisées pour sa zone.

# Identité
- Nom : {{NOM}} · domaine : {{DOMAINE}} (site) et {{API}} (API)
- Pays principal : {{PAYS}} · devise : XOF (F CFA, pas de centimes)
- Couleurs : principale {{C1}}, secondaire {{C2}} · ambiance : {{STYLE}}
- Logo : fichiers dans le dossier brand/
- Interface en français, pensée d'abord pour le téléphone (la page d'achat est ouverte depuis le Wi-Fi sur un mobile), thème clair et sombre avec bascule.
- WhatsApp d'assistance : {{WA}}

# Technique imposée
- Monorepo : dossier frontend/ (React 18 + Vite + Tailwind CSS + React Router, icônes lucide-react, graphiques recharts) et dossier backend/ (Node.js + Express, en CommonJS).
- Base de données : Supabase (PostgreSQL). Le backend y accède uniquement avec la clé service_role ; l'autorisation est vérifiée dans le code (chaque zone a un owner_id). Le frontend ne parle jamais directement à la base : il passe par l'API.
- Authentification : JWT + mots de passe hachés avec bcrypt.
- Paiement : Moneroo (API REST + webhooks signés).
- Hébergement prévu : frontend sur Vercel, backend sur Render.

# Règles de travail
1. Commence par : git init, un .gitignore (node_modules, .env, .env.*, sauf les fichiers .env.example, logs, dist), un README.md et un fichier CLAUDE.md qui résume ce brief et ces règles pour les sessions futures.
2. On avance par phases. À la fin de chaque phase : arrête-toi, résume ce qui a été fait, donne-moi les étapes exactes pour tester, et attends que j'écrive « validé ». Ne commence jamais la phase suivante sans mon accord.
3. Quand je valide une phase, fais un commit Git avec un message clair en français.
4. Aucun secret dans le code : tout passe par des variables d'environnement, documentées dans backend/.env.example et frontend/.env.example.
5. Si une décision te semble risquée ou ambiguë, pose-moi la question au lieu de deviner.

# Phase 1 : maquette (maintenant)
Construis uniquement le frontend, avec des données d'exemple en dur (aucun backend, aucune base) :
- Page d'accueil publique de {{NOM}} (présentation, comment ça marche en 3 étapes, bouton « Acheter un ticket », lien « Retrouver mon ticket »).
- Page d'achat d'une zone (/acheter/:zoneId) : liste des tarifs en cartes, champ numéro de téléphone avec indicatif du pays, bouton payer.
- Page de retour de paiement : état « paiement en cours », puis ticket affiché (identifiant + mot de passe en gros, bouton copier, rappel de la durée).
- Page « Retrouver mon ticket » par numéro.
- Connexion et inscription du gérant.
- Espace gérant avec menu latéral (repliable sur mobile) : Tableau de bord, Zones Wi-Fi, Tarifs, Tickets, Comptabilité, Portail captif, Profil.
Applique la charte : couleurs, logo, polices Google Fonts cohérentes avec l'ambiance. Lance le serveur de développement et donne-moi l'adresse à ouvrir.

Ce qui va se passer

  1. Claude lit le dossier, puis propose de lancer des commandes (git init, npm create vite, npm install…). Accepte-les.
  2. Il crée les fichiers. Tu les vois apparaître dans l'explorateur à gauche.
  3. Il lance npm run dev et te donne une adresse du type http://localhost:5173. Ouvre-la dans ton navigateur.
  4. Il s'arrête et attend ta validation.
Si Claude s'arrête au milieuÉcris simplement « continue ». S'il bloque sur une erreur, copie le message d'erreur complet du terminal et colle-le-lui.

Checklist du chapitre

08

Valider la maquette

C'est le moment le moins cher pour tout changer.

Avant d'écrire la moindre ligne de logique, l'apparence doit te plaire. Changer une couleur maintenant prend 30 secondes ; après la phase 5, ça touche 40 fichiers.

Ce qu'il faut vérifier

  • Sur téléphone : dans le navigateur, F12 puis l'icône téléphone (mode responsive), largeur 375 px. La page d'achat doit être parfaite sur mobile : c'est là que tes clients paient.
  • Couleurs : le texte reste lisible partout, en clair comme en sombre. Les boutons « Payer » se voient au premier coup d'œil.
  • Logo : net, bien proportionné, présent dans l'onglet du navigateur.
  • Textes : clairs pour quelqu'un qui n'a jamais acheté de ticket en ligne.

Prompts de retouche

Sois précis : une page, un problème, le résultat attendu. Tu peux aussi coller une capture d'écran dans la conversation.

Exemples · Claude Code
Sur la page d'achat, les cartes de tarifs sont trop petites sur mobile : affiche-les en une colonne pleine largeur sous 480 px, prix en très gros, durée en dessous.

Le vert {{C1}} est trop clair sur fond blanc pour le texte : garde-le pour les boutons mais utilise une version plus foncée pour les liens.

En thème sombre, le tableau de bord manque de contraste entre les cartes et le fond. Corrige-le sans toucher au thème clair.

Quand tout te plaît :

Validation · Claude Code
Validé. Fais le commit de la phase 1, puis décris-moi la phase 2 avant de la commencer.

Checklist du chapitre

09

Créer Supabase et Moneroo

Les deux services dont le code aura besoin pour fonctionner.

Supabase (base de données)

  1. Va sur supabase.com, connecte-toi avec GitHub (crée d'abord ton compte GitHub sur github.com).
  2. New project : nom , mot de passe de base de données fort (garde-le dans un gestionnaire de mots de passe), région la plus proche (Europe, ex. Francfort ou Paris).
  3. Attends 2 minutes la création, puis va dans Project Settings → API (ou « API Keys »).
  4. Note trois valeurs : Project URL, la clé anon / publishable et la clé service_role / secret.
Clé service_roleElle donne tous les droits sur ta base. Elle ne va que dans le fichier backend/.env et dans les variables de Render. Jamais dans le frontend, jamais dans une capture d'écran, jamais dans un message.

Moneroo (paiement)

  1. Crée un compte sur moneroo.io.
  2. Lance la vérification de ton entreprise (KYC) tout de suite : pièce d'identité, justificatif d'activité. Elle peut prendre plusieurs jours et elle est obligatoire pour encaisser de vrais paiements.
  3. En attendant, reste en mode test (sandbox) : dans Developers → API Keys, copie la clé secrète de test (elle commence par test_). Une passerelle de démonstration permet de simuler des paiements.
  4. Dans les réglages de paiement, active les méthodes de ton pays (MTN, Moov, Orange, Wave…). Une méthode non activée n'apparaît pas aux clients, même si ton code la demande.
  5. Le webhook se configure au chapitre 11, quand ton API aura une adresse publique.

Les méthodes par pays

PaysIndicatifCodes Moneroo
Bénin229mtn_bj moov_bj celtiis_bj
Côte d'Ivoire225mtn_ci orange_ci moov_ci wave_ci
Togo228moov_tg togocel
Sénégal221orange_sn wave_sn freemoney_sn e_money_sn wizall_sn
Mali223orange_ml moov_ml
Burkina Faso226orange_bf moov_bf
Leçon apprise en productionUn seul code de méthode inconnu de Moneroo fait rejeter tout le paiement. Fô-Zône l'a vécu avec un code Mali présent dans la documentation mais refusé par l'API : aucun achat n'aboutissait. Teste chaque pays que tu ouvres. Moneroo refuse aussi tout montant inférieur à 100 F CFA.

Checklist du chapitre

10

Construire les fonctions, phase par phase

Un prompt par phase. Teste, valide, puis passe à la suivante.

Chaque phase ci-dessous contient le prompt à envoyer et la façon de vérifier le résultat. Ne saute pas les tests : une erreur trouvée en phase 3 coûte une minute, la même trouvée après la mise en ligne coûte des clients.

Phase 2 Base de données

Prompt · Phase 2
Phase 2 : la base de données Supabase.
Écris backend/database/schema.sql, à exécuter dans le SQL Editor de Supabase, avec :
- users : id uuid, email unique, mot de passe haché, nom, téléphone, rôle (admin, super_admin), dates.
- wifi_zones : id, owner_id → users, nom, pays (code BJ, CI, TG, SN, ML, BF), adresse, router_ip (accepte une IP ou un nom d'hôte), téléphone du gérant, latitude/longitude facultatives, actif, dates.
- pricings : id, wifi_zone_id, nom, montant (entier, F CFA, minimum 100), durée en heures, profil MikroTik associé, actif.
- tickets : id, wifi_zone_id, pricing_id, username, password, profile, statut (free, reserved, sold, expired), payment_id, sold_at. Unicité (wifi_zone_id, username).
- payments : id, moneroo_payment_id unique, wifi_zone_id, pricing_id, montant, téléphone normalisé, méthode réellement utilisée (code Moneroo), statut (pending, completed, failed, cancelled), ticket_id, et un instantané du tarif au moment de la vente (pricing_name, pricing_duration_hours) pour que supprimer un tarif ne casse jamais l'historique.
- payment_idempotency : clé unique (événement + id de paiement), pour ne jamais traiter deux fois le même webhook.
- Une fonction PostgreSQL assign_ticket_atomic(zone, tarif, paiement) qui choisit UN ticket libre de ce tarif avec FOR UPDATE SKIP LOCKED, le passe en sold, le lie au paiement, et ne renvoie rien s'il n'y en a plus. Jamais de ticket d'un autre tarif en remplacement.
- Index utiles, triggers updated_at.
Pour les évolutions futures, crée un dossier backend/database/migrations/ avec des fichiers numérotés (001_..., 002_...).
Explique-moi ensuite, pas à pas, comment exécuter le script dans Supabase et comment vérifier que les tables existent.

Vérifier : dans Supabase, SQL Editor → New query, colle le contenu de schema.sql, clique Run. Puis Table Editor : les 6 tables doivent apparaître.

Phase 3 API, sécurité et connexion

Prompt · Phase 3
Phase 3 : le backend Express et l'authentification.
- Structure backend/src : config/ (database, logger, countries), controllers/, routes/, middleware/ (auth, validator, errorHandler), services/, utils/. Point d'entrée src/server.js, scripts npm « dev » (nodemon) et « start ».
- Sécurité : helmet, CORS avec une liste d'origines séparées par des virgules (CORS_ORIGIN), limitation de débit, express-validator sur toutes les entrées, logs avec winston (jamais de mot de passe ni de clé dans les logs).
- Route GET /api/health qui répond { status: "ok" }.
- Auth : POST /api/auth/register, POST /api/auth/login, GET et PUT /api/auth/profile, PUT /api/auth/profile/password. JWT signé avec JWT_SECRET, expiration JWT_EXPIRES_IN.
- backend/.env.example complet et commenté (PORT, NODE_ENV, API_BASE_URL, FRONTEND_URL, SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY, JWT_SECRET, JWT_EXPIRES_IN, MONEROO_API_KEY, MONEROO_WEBHOOK_SECRET, MONEROO_BASE_URL, CORS_ORIGIN, LOG_LEVEL).
- Côté frontend : remplace les données d'exemple de connexion et d'inscription par les vrais appels (axios, VITE_API_URL), garde le jeton, protège les pages du gérant.
Dis-moi exactement quoi mettre dans backend/.env et frontend/.env.development.local (sans jamais me demander de coller mes clés dans la conversation), puis comment lancer les deux serveurs.

Vérifier : crée ton backend/.env à partir de .env.example et remplis-le toi-même. Pour JWT_SECRET, génère une chaîne aléatoire (voir ci-dessous). Ouvre http://localhost:3000/api/health : tu dois voir "status":"ok". Inscris-toi, déconnecte-toi, reconnecte-toi.

PowerShell · générer JWT_SECRET
-join ((48..57) + (65..90) + (97..122) | Get-Random -Count 64 | % {[char]$_})
Tes clés, toi seulRemplis les fichiers .env toi-même dans l'éditeur. Claude n'a pas besoin de voir tes clés pour écrire le code qui les utilise.

Phase 4 Zones, tarifs et tickets

Prompt · Phase 4
Phase 4 : zones, tarifs et tickets.
- CRUD des zones (/api/wifi-zones) : chaque requête vérifie que la zone appartient à l'utilisateur connecté (owner_id). Route publique GET /api/wifi-zones/public/:id qui ne renvoie que ce dont la page d'achat a besoin (nom, pays, actif).
- CRUD des tarifs par zone (/api/pricings/zone/:zoneId), route publique des tarifs actifs. Refuse un montant sous 100 F CFA. Supprimer un tarif déjà vendu ne doit pas casser l'historique (instantané dans payments).
- Tickets : import CSV (multer + csv-parser) qui accepte les colonnes Username/username, Password/password, Profile/profile, lie chaque ticket au tarif dont le profil correspond, ignore les doublons et renvoie un résumé (importés, doublons, erreurs). Liste paginée avec filtre par statut, statistiques par zone, alerte quand il reste moins de 10 tickets libres pour un tarif. Un ticket vendu ne peut être ni modifié ni supprimé.
- Ajoute dans la page Tickets un générateur de lot : je choisis un tarif et une quantité, il produit des identifiants et mots de passe aléatoires lisibles (sans 0/O ni 1/l), puis me donne (a) le fichier CSV à importer et (b) le script RouterOS « /ip hotspot user add » à coller dans le terminal du routeur.
- Branche les pages Zones, Tarifs et Tickets du frontend sur ces routes.

Vérifier : crée une zone, deux tarifs (ex. 200 F / 1 h et 500 F / 24 h), génère 20 tickets par tarif, importe le CSV. Le compteur de tickets libres doit afficher 20 par tarif. Importe le même fichier une deuxième fois : il doit annoncer 40 doublons et rien de plus.

Phase 5 Paiement Mobile Money

La phase la plus importante. Lis le prompt avant de l'envoyer : chaque ligne correspond à un problème réel rencontré en production.

Prompt · Phase 5
Phase 5 : le paiement avec Moneroo. Lis la documentation officielle de Moneroo (initialisation de paiement, vérification, webhooks, méthodes disponibles) avant d'écrire le code.
- backend/src/config/countries.js : pour chaque pays (BJ, CI, TG, SN, ML, BF), le nom, l'indicatif, un exemple de numéro et la liste des codes de méthodes Moneroo. Fonction normalizePhone qui ajoute l'indicatif sans retirer le zéro initial des numéros locaux (Bénin et Côte d'Ivoire ont des numéros à 10 chiffres). Le numéro stocké en base doit être exactement celui envoyé à Moneroo.
- POST /api/payments/intent (public) : reçoit zoneId, pricingId, téléphone. Relit le montant depuis la base (jamais celui envoyé par le navigateur), vérifie qu'il reste au moins un ticket libre de ce tarif AVANT de faire payer, crée le paiement Moneroo avec les méthodes du pays de la zone, une return_url vers la page de retour du frontend, et des métadonnées (zone, tarif, paiement). Enregistre le paiement en pending avec l'instantané du tarif.
- En mode test (clé commençant par « test_ »), ajoute la passerelle de démonstration Moneroo aux méthodes.
- POST /api/payments/moneroo/webhook : vérifie la signature HMAC-SHA256 avec MONEROO_WEBHOOK_SECRET sur le corps BRUT de la requête (express.raw sur cette route uniquement, pas sur un JSON re-sérialisé). Rejette toute signature invalide. Idempotence sur événement + id. Sur succès : re-vérifie le statut auprès de l'API Moneroo, enregistre la méthode réellement utilisée, puis appelle assign_ticket_atomic. Le client reçoit un ticket du tarif payé, ou aucun ; jamais un autre tarif. S'il n'y en a plus, marque le paiement pour remboursement et journalise une alerte.
- GET /api/payments/:id (public, données minimales) : la page de retour l'interroge toutes les 3 secondes pendant 2 minutes, puis affiche le ticket.
- GET /api/payments/lookup/:phone (public, limité en débit) : retrouve les tickets achetés avec ce numéro, quelle que soit la façon dont le client l'écrit (avec ou sans indicatif).
- Branche la page d'achat, la page de retour et « Retrouver mon ticket ».
Explique-moi comment tester en local avec la passerelle de démonstration, sachant que Moneroo ne peut pas appeler mon localhost.

Vérifier : en local, Moneroo ne peut pas joindre ton ordinateur ; Claude te proposera soit un tunnel (ngrok, cloudflared), soit d'attendre la mise en ligne (chapitre 11) pour le test complet. Vérifie au minimum que la page de paiement Moneroo s'ouvre avec les bons opérateurs et le bon montant.

Sans secret de webhook, aucun ticketSi MONEROO_WEBHOOK_SECRET est vide ou faux, tous les webhooks sont rejetés : les clients paient et ne reçoivent rien. C'est la première chose à vérifier si un paiement réussi n'affiche pas de ticket.

Phase 6 Tableau de bord et comptabilité

Prompt · Phase 6
Phase 6 : tableau de bord et comptabilité.
- Centralise le taux de commission de l'agrégateur dans backend/src/config/commission.js (je te donnerai le taux réel de mon contrat Moneroo ; mets 2 % par défaut). Arrondi au franc entier, ligne par ligne, jamais sur une somme.
- GET /api/dashboard/stats : recettes du jour (brut et net), chiffre d'affaires total, tickets vendus, tickets restants, zones actives. Statistiques par zone et par période.
- Comptabilité (/api/accounting) : ventes par jour (brut, commission, net), tickets vendus par tarif, répartition par opérateur (MTN, Moov, Orange…, avec leurs noms lisibles), historique paginé des paiements avec le ticket attribué, export CSV.
- Frontend : graphiques recharts, filtres par zone et par période, chiffres alignés, tout lisible sur mobile.
- Optimise : requêtes en parallèle, chargement page par page, squelettes de chargement.

Vérifier : la somme des lignes « net » doit être égale au total net affiché. Exporte le CSV et ouvre-le dans Excel.

Phase 7 Générateur de portail captif

Prompt · Phase 7
Phase 7 : la page « Portail captif » du tableau de bord.
Le gérant choisit sa zone, un style parmi trois, le nom affiché, un pied de page et le numéro WhatsApp ({{WA}} par défaut), voit un aperçu, puis télécharge login.html et redirect.html déjà remplis.
- Gabarits dans frontend/src/templates/captivePortal.js.
- login.html : formulaire de connexion MikroTik standard (les variables RouterOS $(link-login-only), $(username), $(error), etc. doivent rester intactes, ainsi que l'usage de md5.js fourni par MikroTik), un gros bouton « Acheter un ticket » vers https://{{DOMAINE}}/acheter/ID_DE_LA_ZONE, un lien « Retrouver mon ticket », et le lien WhatsApp.
- redirect.html : redirection après connexion.
- Pas de dépendance externe dans les pages (styles en ligne), elles doivent fonctionner avant que le client ait internet.
- Fournis aussi, à copier, le bloc walled garden RouterOS qui autorise avant connexion : {{DOMAINE}}, www.{{DOMAINE}}, {{API}}, checkout.moneroo.io, api.moneroo.io, les domaines de la passerelle utilisée par Moneroo (ex. process.fedapay.com, api.fedapay.com), fonts.googleapis.com, fonts.gstatic.com, et wa.me + api.whatsapp.com si un WhatsApp est renseigné. Utilise « /ip hotspot walled-garden ip » (c'est lui qui laisse passer le HTTPS) en plus de « /ip hotspot walled-garden ».
- Ajoute la marche à suivre sur le routeur, en français simple.
- L'aperçu dans le navigateur remplace les variables $(...) par des valeurs d'exemple, mais le fichier téléchargé garde les variables brutes.

Vérifier : télécharge les deux fichiers, ouvre login.html avec un éditeur de texte et cherche $(link-login-only) : il doit être présent tel quel.

Phase 8 · facultative Ouvrir la plateforme à d'autres gérants

Si tu veux vendre ton système à d'autres gérants plutôt que l'utiliser seul. C'est le modèle de Fô-Zône.

Prompt · Phase 8
Phase 8 : mode plateforme multi-gérants.
- Rôle super_admin (moi) en plus des gérants. Inscription libre des gérants.
- Commission plateforme de 5 % sur chaque ticket vendu, commission de l'agrégateur INCLUSE dans ces 5 % (c'est mon coût, pas celui du gérant). Exemple : ticket 200 F → 10 F pour {{NOM}}, 190 F pour le gérant. Enregistre platform_fee sur chaque paiement, arrondi au franc par paiement. Affiche clairement ce taux au gérant.
- Portefeuille du gérant : solde disponible = ventes nettes − retraits. Demande de retrait vers un numéro Mobile Money.
- Le retrait n'est possible qu'après vérification d'identité du gérant (pièce + selfie), validée par le super-admin.
- Espace super-admin : liste des gérants (valider, suspendre), demandes de retrait (approuver, marquer payé, refuser avec motif), vue globale des ventes.
- Partage de compte : un gérant peut inviter un membre d'équipe avec un accès limité à ses zones.
Toutes ces règles d'argent doivent être vérifiées côté serveur.

Phase 9 Préparer la mise en ligne

Prompt · Phase 9
Phase 9 : préparation de la production.
- frontend/vercel.json avec une réécriture de toutes les routes vers /index.html (sinon un rafraîchissement sur /acheter/... donne une erreur 404).
- Vérifie que « npm run build » du frontend passe sans erreur et que le backend démarre avec « npm start ».
- Le backend doit lire le port fourni par l'hébergeur (process.env.PORT) et faire confiance au proxy (app.set('trust proxy', 1)) pour la limitation de débit.
- Relis tout le code à la recherche de secrets en dur, de routes sans vérification de propriétaire et de montants acceptés depuis le navigateur. Corrige ce que tu trouves.
- Mets à jour le README : installation, variables d'environnement, déploiement Vercel + Render, configuration du webhook Moneroo.
Puis donne-moi les commandes pour créer le dépôt GitHub privé et pousser le code.

Checklist du chapitre

11

Mettre en ligne : Render, Vercel et DNS

L'API d'abord, le site ensuite, le webhook pour finir.

1. L'API sur Render

  1. Crée un compte sur render.com avec GitHub.
  2. New → Web Service, choisis ton dépôt.
  3. Réglages : Root Directory backend · Build Command npm install · Start Command npm start · région Francfort · plan Starter.
  4. Dans Environment, ajoute chaque variable de ton backend/.env avec les valeurs de production :
Variables Render
NODE_ENV=production
API_BASE_URL=https://{{API}}
FRONTEND_URL=https://{{DOMAINE}}
CORS_ORIGIN=https://{{DOMAINE}},https://www.{{DOMAINE}}
SUPABASE_URL=            (ta Project URL)
SUPABASE_SERVICE_ROLE_KEY=   (ta clé service_role)
JWT_SECRET=              (une NOUVELLE chaîne de 64 caractères)
JWT_EXPIRES_IN=7d
MONEROO_API_KEY=         (test_... pour commencer)
MONEROO_WEBHOOK_SECRET=  (rempli à l'étape 4)
MONEROO_BASE_URL=https://api.moneroo.io
LOG_LEVEL=info
  1. Lance le déploiement. Quand il est vert, ouvre https://ton-service.onrender.com/api/health.
  2. Settings → Custom Domains : ajoute . Render t'indique un enregistrement CNAME à créer.

2. Le site sur Vercel

  1. Crée un compte sur vercel.com avec GitHub.
  2. Add New → Project, importe ton dépôt.
  3. Root Directory : frontend. Vercel détecte Vite tout seul (build npm run build, sortie dist).
  4. Variables d'environnement :
Variables Vercel
VITE_API_URL=https://{{API}}/api
VITE_FRONTEND_URL=https://{{DOMAINE}}
  1. Deploy. Puis Settings → Domains : ajoute et www.. Vercel affiche les enregistrements DNS à créer.
Variables VITE_Elles sont lues au moment du build. Si tu en modifies une, relance un déploiement pour qu'elle soit prise en compte.

3. Les DNS chez ton registraire

Dans la gestion DNS de ton domaine, crée les enregistrements que Vercel et Render t'ont affichés. En général :

TypeNom / HôteValeurPour
A@l'adresse IP donnée par Vercelle site
CNAMEwwwla cible donnée par Vercelle site avec www
CNAMEapiton-service.onrender.coml'API

Supprime les anciens enregistrements A ou CNAME « parking » créés par le registraire sur @ et www. La propagation prend de 5 minutes à quelques heures ; le certificat HTTPS est ensuite créé automatiquement.

4. Le webhook Moneroo

  1. Dans Moneroo, Developers → Webhooks, ajoute l'URL :
URL du webhook
https://{{API}}/api/payments/moneroo/webhook
  1. Copie le secret de signature affiché et colle-le dans MONEROO_WEBHOOK_SECRET sur Render. Render redéploie automatiquement.
  2. Fais un achat de test avec la passerelle de démonstration : le ticket doit s'afficher sur la page de retour en quelques secondes.

5. Passer en production

  1. Quand le KYC Moneroo est validé, remplace la clé test_ par la clé de production sur Render.
  2. Le webhook de production peut avoir son propre secret : vérifie-le.
  3. Achète un vrai ticket au tarif le plus bas avec ton propre Mobile Money. Vérifie qu'il apparaît dans la comptabilité avec le bon opérateur.

Checklist du chapitre

12

Configurer le routeur MikroTik

Le hotspot, les profils, les tickets et ton portail.

1. Activer le hotspot

  1. Installe Winbox (sur mikrotik.com/download) et connecte-toi au routeur.
  2. Mets RouterOS à jour : System → Packages → Check For Updates.
  3. IP → Hotspot → Hotspot Setup : choisis l'interface (le bridge Wi-Fi des clients), garde les plages d'adresses proposées, DNS name par exemple login.wifi. Ne crée pas d'utilisateur à la fin.

2. Les profils (un par tarif)

Le nom du profil doit être exactement celui saisi dans le tarif sur ta plateforme : c'est lui qui relie un ticket à son tarif.

Terminal RouterOS · exemple
/ip hotspot user profile
add name=1h  shared-users=1 rate-limit=2M/5M  session-timeout=1h
add name=24h shared-users=1 rate-limit=3M/8M  session-timeout=1d
add name=7j  shared-users=1 rate-limit=3M/8M
Durée réellesession-timeout limite une session continue. Pour un forfait qui expire au bout d'une durée totale, utilise la colonne limit-uptime des utilisateurs (le générateur de la phase 4 peut l'ajouter) ou le paquet User Manager. Demande à Claude d'adapter le script selon ton choix.

3. Créer et importer les tickets

  1. Dans ton tableau de bord, page Tickets, générateur de lot : choisis le tarif et la quantité.
  2. Copie le script RouterOS et colle-le dans New Terminal de Winbox : les utilisateurs sont créés sur le routeur.
  3. Importe le CSV correspondant dans la même page : les mêmes tickets sont maintenant en vente.
Toujours les deuxUn ticket présent sur la plateforme mais absent du routeur sera vendu et refusé à la connexion. Importe toujours le script ET le CSV du même lot.

4. Installer ton portail

  1. Dans le tableau de bord, page Portail captif : choisis la zone, le style, télécharge login.html et redirect.html.
  2. Dans Winbox, Files : ouvre le dossier hotspot (ou flash/hotspot) et glisse-dépose les deux fichiers pour remplacer ceux d'origine. Garde md5.js et le dossier img : sans eux, la connexion casse.
  3. Copie le bloc walled garden fourni par la page et colle-le dans le terminal.

Le bloc ressemble à ceci, avec tes domaines :

Terminal RouterOS
/ip hotspot walled-garden ip
add action=accept dst-host={{DOMAINE}} comment="{{NOM}} portail"
add action=accept dst-host=www.{{DOMAINE}} comment="{{NOM}} portail"
add action=accept dst-host={{API}} comment="{{NOM}} API"
add action=accept dst-host=checkout.moneroo.io comment="Moneroo checkout"
add action=accept dst-host=api.moneroo.io comment="Moneroo API"
add action=accept dst-host=process.fedapay.com comment="Passerelle"
add action=accept dst-host=api.fedapay.com comment="Passerelle"
add action=accept dst-host=fonts.googleapis.com comment="Polices"
add action=accept dst-host=fonts.gstatic.com comment="Polices"
add action=accept dst-host=wa.me comment="Assistance WhatsApp"
add action=accept dst-host=api.whatsapp.com comment="Assistance WhatsApp"

/ip hotspot walled-garden
add action=allow dst-host={{DOMAINE}}
add action=allow dst-host=*.{{DOMAINE}}
add action=allow dst-host=*.moneroo.io
add action=allow dst-host=*.fedapay.com
Si la page de paiement ne s'ouvre pasDepuis le téléphone connecté au Wi-Fi sans ticket, ouvre la page d'achat et note l'adresse qui reste bloquée. Ajoute ce domaine au walled garden. La passerelle derrière Moneroo peut changer selon le pays et l'opérateur.

Checklist du chapitre

13

Le test complet, puis le lancement

Mets-toi dans la peau d'un client, sur un téléphone qui ne connaît pas ton système.

  1. Oublie le réseau Wi-Fi sur ton téléphone, reconnecte-toi : le portail doit s'afficher automatiquement.
  2. Touche « Acheter un ticket » : la page d'achat s'ouvre sans ticket ni connexion internet préalable.
  3. Choisis le tarif le moins cher, saisis ton numéro, paie.
  4. Le ticket s'affiche. Reviens au portail, connecte-toi avec : internet fonctionne.
  5. Ferme tout, utilise « Retrouver mon ticket » avec ton numéro : le ticket est retrouvé.
  6. Dans le tableau de bord : la vente apparaît, avec le bon opérateur, le stock a baissé de 1.

Avant d'ouvrir au public

Ta zone vend toute seule

Ensuite, ton travail se résume à trois gestes : recharger les tickets quand l'alerte de stock apparaît, regarder la comptabilité, et demander à Claude les améliorations que tes clients réclament.

14

Dépannage et entretien

Les pannes réellement rencontrées, et comment travailler avec Claude dans la durée.

Le client a payé mais aucun ticket ne s'affiche

Dans l'ordre : (1) MONEROO_WEBHOOK_SECRET correct sur Render ? (2) L'URL du webhook dans Moneroo pointe bien vers ? (3) Logs Render : cherche « signature ». (4) Reste-t-il des tickets libres de ce tarif ? Le paiement est alors marqué pour remboursement.

La page Moneroo n'affiche pas mon opérateur

La méthode n'est pas activée dans ton tableau de bord Moneroo, ou la zone n'a pas le bon pays. Vérifie les deux.

« The payment method … is invalid »

Un code de méthode n'est pas accepté par Moneroo. Retire-le de countries.js : un seul code invalide bloque tout le paiement.

Erreur CORS dans la console du navigateur

CORS_ORIGIN sur Render doit contenir l'adresse exacte du site, avec https et sans barre finale, et aussi la version www.

Erreur 404 quand on rafraîchit une page du site

Il manque frontend/vercel.json avec la réécriture vers /index.html.

« Colonne inconnue » après une mise à jour

Une migration n'a pas été exécutée dans Supabase. Exécute dans l'ordre les fichiers de backend/database/migrations/ qui manquent.

Le ticket est vendu mais refusé sur le portail

Il n'existe pas sur le routeur, ou son profil ne porte pas le même nom. Vérifie dans IP → Hotspot → Users.

Le portail affiche du texte comme $(username)

Tu ouvres le fichier en dehors du routeur. Sur le routeur, ces variables sont remplacées automatiquement. Ne les modifie jamais à la main.

Travailler avec Claude dans la durée

  • Une demande = une conversation. Pour une nouvelle fonction, ouvre une nouvelle session : Claude relit CLAUDE.md et repart propre.
  • Décris le problème, pas la solution. « Les clients du Togo ne voient que Moov » vaut mieux que « modifie countries.js ».
  • Colle les erreurs en entier, avec la page et l'action qui l'ont provoquée.
  • Commit avant chaque gros changement. Si ça tourne mal : « annule tout depuis le dernier commit ».
  • Demande une relecture avant chaque mise en ligne importante : « relis les changements depuis le dernier déploiement et cherche les bugs liés à l'argent ».
Prompt d'entretien · exemple
Un client de {{NOM}} a payé 500 F ce matin vers 9 h avec le numéro 01 XX XX XX XX, Moneroo indique « success », mais il n'a pas reçu de ticket. Explique-moi comment retrouver ce paiement, pourquoi le ticket n'a pas été attribué, et corrige la cause. Ne touche à aucun autre paiement.

Mettre à jour la plateforme

  1. Demande la modification à Claude, teste en local.
  2. Valide ; Claude fait le commit et le git push.
  3. Vercel et Render redéploient automatiquement à chaque push sur la branche principale.
  4. Si la modification ajoute une migration SQL, exécute-la dans Supabase avant le push.

Sécurité : la liste à garder sous la main

  • Le dépôt GitHub est privé.
  • La clé service_role, le JWT_SECRET et les clés Moneroo ne vivent que dans .env (local) et dans Render.
  • Si une clé a fuité (capture d'écran, message, commit) : régénère-la immédiatement chez le fournisseur et remplace-la sur Render.
  • Le montant facturé est toujours relu depuis la base, la signature du webhook toujours vérifiée.
  • Active la double authentification sur GitHub, Vercel, Render, Supabase, Moneroo et ton registraire.