Captore est une mission freelance : un SaaS destiné aux commerces qui vendent des produits à forte valeur, où chaque visiteur compte. Je l’ai conçu, développé et mis en production seul, du cadrage avec le client jusqu’au déploiement. Le développement a duré moins d’un mois, de fin avril à fin mai 2026, en quatre phases. Le client fournissait l’hébergement et les comptes des services tiers. La plateforme tourne aujourd’hui en production dans un premier établissement pilote.
La cible · Le problème
Ces commerces accueillent des visiteurs en magasin ou sur des salons, puis en perdent la trace faute de suivi. Recueillir les coordonnées, comprendre le besoin, relancer au bon moment par le bon canal, savoir quel vendeur a apporté quel contact : tout cela restait manuel et dispersé. Les avis Google, décisifs pour la visibilité locale, étaient rarement demandés au bon moment.
Le client voulait une plateforme unique, que chaque établissement configure seul, sans outil de pistage ni de publicité tiers.
Le plan · La solution
Le visiteur scanne un QR code affecté à un vendeur. Les codes tournent automatiquement entre les vendeurs actifs. Il suit ensuite un parcours mobile : formulaire de contact avec consentement RGPD, questionnaire présenté comme une conversation, puis une page de résultats personnalisée selon ses réponses. Il peut demander à être rappelé, laisser un avis Google ou tenter sa chance à un jeu pour gagner un cadeau.
Côté établissement, le gérant règle tout depuis son back-office : questionnaires, ordre du parcours, jeux et lots, modèles de messages, relances automatiques par e-mail, SMS et WhatsApp. Il suit ses prospects (statut, notes, chiffre d’affaires signé, historique des échanges), envoie des propositions commerciales et voit quand elles sont consultées, et pilote son activité sur un tableau de bord. Un espace d’administration générale gère tous les établissements, les réglages communs et le journal d’audit.
Scan du QR codeattribué à un vendeurFormulairecontact et consentement RGPDQuestionnaireprésenté comme une conversationRésultatspersonnalisés selon les réponsesRappelez-moitéléphone, rendez-vous, SMS ou e-mailAvis Googlelaisser un avisJeuun cadeau à gagnerau choix du visiteurRelancese-mail, SMS et WhatsApp, planifiées
Scan du QR codeattribué à un vendeurFormulairecontact et consentement RGPDQuestionnaireprésenté comme une conversationRésultatspersonnalisés selon les réponsesau choix du visiteurRappelez-moitéléphone, SMS ou e-mailAvis Googlelaisser un avisJeuun cadeau à gagnerRelancese-mail, SMS et WhatsApp, planifiées
Parcours du visiteur : scan, formulaire, questionnaire, résultats, rappel, avis ou jeu, relances
Parcours visiteursur mobile, après le scan du QR codeBack-officegérants et administration généraleConteneurs DockerInterface Vue 3TypeScript, Vuetify, servie par NginxAPI REST Laravelversionnée, authentification SanctumIsolation des établissementsMySQLbase unique, filtrée par établissementRediscache et filesFiles et planificateurSMS et WhatsAppTwilioE-mailSMTP propre à chaque établissementRappeltéléphonieHTTPSHTTPSRESTrelances et rappels
Parcours visiteurmobile, après le scanBack-officegérants et administrationConteneurs DockerInterface Vue 3TypeScript, Vuetify, NginxAPI REST Laravelauthentification SanctumIsolation des établissementsMySQLbase uniqueRediscache et filesFiles et planificateurSMS et WhatsAppTwilioE-mailSMTP par établissementRappeltéléphonieREST
Schéma d’architecture de Captore : interface Vue, API Laravel, MySQL et Redis, tâches planifiées, canaux SMS et e-mail
L’exécution · Ce que j’ai réalisé
Le cadrage : arbitrage des choix structurants avec le client (isolation des établissements, organisation du code, intégrations), découpage en quatre phases, tenue du périmètre et du planning.
L’isolation des établissements : une base unique où chaque donnée porte son établissement, un filtre global posé automatiquement, et des tests qui vérifient qu’aucun établissement ne voit les données d’un autre.
L’API : REST versionnée, authentification Sanctum, consommée par une application Vue 3 en TypeScript et prête à servir une future app mobile sans refonte.
L’organisation du code : douze domaines métier, du QR code à l’audit.
Les QR codes : génération, rotation entre vendeurs actifs sans conflit, attribution figée au moment du scan.
Le questionnaire : quatre types de réponse, et un moteur de règles conditionnelles qui choisit les images et les messages des résultats.
Les jeux : roue et cartes à retourner, avec des plafonds de participation configurables.
Les relances : e-mail, SMS et WhatsApp via Twilio, modèles éditables avec variables, relances planifiées, liens suivis.
Le rappel : un bouton « Rappelez-moi » qui fonctionne par téléphone, par prise de rendez-vous, par SMS ou par e-mail.
Le suivi commercial : fiches prospects, propositions commerciales consultables par lien avec notification d’ouverture, export CSV.
L’administration générale : connexion à la place d’un gérant avec bandeau et traçabilité, tableau de bord global, réglages communs surchargeables, journal d’audit avant et après chaque modification.
Le déploiement : image Docker de production en plusieurs étapes, préproduction et production en conteneurs, stockage persistant des fichiers, tâches planifiées.
Le matériel · Stack technique
Front : Vue 3, TypeScript, Vuetify 3, Pinia, Vite, éditeur de texte riche, graphiques.
Back : Laravel, PHP 8.5, Laravel Sanctum, gestion des rôles, journal d’activité, files d’attente et planificateur.
Données : MySQL 8.4, Redis.
Services : Twilio pour les SMS et WhatsApp, SMTP propre à chaque établissement, téléphonie pour le rappel.
Livraison : Docker, Nginx, environnements séparés de développement, préproduction et production.
Incident n°1 : isoler les établissements sans dépendance lourde
Imprévu. Chaque établissement ne doit jamais voir les données d’un autre. Un paquet de gestion multi-locataires aurait coûté du temps d’apprentissage, sur un calendrier de quelques semaines.
Parade. Une base unique, un identifiant d’établissement sur chaque donnée, un filtre global appliqué par un trait Eloquent. L’établissement courant vient de la session dans le back-office, et du jeton signé du QR code dans le parcours public. Chaque modèle a ses tests d’isolation.
Ce que j’en retiens. Une solution native bien testée est souvent plus robuste et plus lisible qu’une dépendance lourde. Et elle laisse la porte ouverte à une base par établissement si le besoin évolue.
Incident n°2 : des réglages communs que certains établissements doivent changer
Imprévu. L’administrateur définit des réglages pour tous (envoi d’e-mails, clés d’API, modèles de messages), mais certains établissements doivent pouvoir utiliser les leurs.
Parade. Un résolveur unique par type de réglage, avec une hiérarchie explicite (établissement, puis réglage commun, puis valeur de la plateforme) et des droits de surcharge accordés établissement par établissement.
Ce que j’en retiens. Écrire la règle de résolution en un seul endroit évite les incohérences entre les écrans et entre les canaux.
Incident n°3 : des images qui disparaissent à chaque déploiement
Imprévu. En conteneur, les images envoyées par les gérants disparaissaient à chaque redéploiement. Après l’ajout d’un volume persistant, l’écriture échouait en silence : réponse 200, aucun fichier.
Parade. Le diagnostic a montré que l’utilisateur www-data n’a pas le même identifiant système sur les images Alpine et Debian. Volume persistant, droits corrigés, et une procédure de vérification après chaque déploiement.
Ce que j’en retiens. En environnement conteneurisé, il faut toujours vérifier les identifiants système et ce que le stockage fait quand il échoue sans rien dire.
Incident n°4 : des boutons morts après une mise en production
Imprévu. Après certains déploiements, des boutons ne répondaient plus. Un simple rafraîchissement réglait le problème, ce qui le rendait difficile à reproduire.
Parade. Le navigateur gardait en cache la page d’entrée de l’application, qui pointait vers des fichiers JavaScript d’une ancienne version. Les chargements à la demande échouaient sans erreur visible. La page d’entrée n’est plus mise en cache, et les fichiers versionnés gardent un cache long.
Ce que j’en retiens. Dans une application monopage, le cache du document d’entrée compte autant que celui des fichiers qu’il charge.
Le bilan · Résultats
Plateforme livrée en quatre phases entre le 28 avril et le 21 mai 2026, puis mise en production.
En production dans un premier établissement pilote.
246 méthodes de test, sur l’isolation des établissements, les droits, le moteur de règles, le tirage du jeu, les relances, le parcours public et l’audit.