SNAP est une chaîne de studios photo en libre-service présente dans six villes indonésiennes. L'ancien site était une brochure statique — les réservations se faisaient par message WhatsApp, chaque agence tenait son propre cahier, et environ une session sur douze se terminait par un conflit à l'entrée. Nous avons reconstruit le parcours client sous forme de PWA et livré un tableau de bord d'administration unique qui couvre les six agences en même temps.
Une PWA mobile-first côté client, une SPA desktop côté administration, une seule API et une seule base de données en dessous. Six modules portent l'ensemble de la chaîne — de l'écran de ville qu'un client voit sur Instagram au récapitulatif journalier qu'un responsable d'agence valide en fin de journée.
Six villes, douze agences, deux types de studios. Le parcours client saute automatiquement l'étape de sélection d'agence dans les villes à studio unique et oriente vers le bon modèle de capacité selon le lieu.
Les studios en box utilisent une matrice fond×horaire — chaque salle se réserve indépendamment. Les studios à fond déroulant fonctionnent sur un planning partagé avec un choix de fond purement esthétique. Même interface, deux règles de capacité différentes en dessous.
Le client scanne un code QRIS dynamique, le callback marchand libère le créneau, le client voit une coche. Personne ne surveille l'application bancaire. Plus de message manuel « c'est payé ? ».
Un seul tableau de bord pour le fondateur. Réservations du jour sur six agences, ventes par rapport à hier, dépenses par catégorie, taux d'occupation par salle. Clic sur n'importe quelle tuile pour accéder aux lignes brutes.
Les responsables d'agence ne voient que leur agence — calendrier du jour, toggle pour les walk-ins, journal de dépenses, caisse de fin de journée. Basé sur les rôles, verrouillé par défaut.
Réservation confirmée → un message WhatsApp formaté part avec le créneau, l'adresse de l'agence et un lien calendrier. Rappel envoyé 2 heures avant. Les DMs ne sont plus l'endroit où vivent les réservations, mais restent celui où les clients s'attendent à avoir des nouvelles.
Chaque agence avait son propre numéro d'administration. Les clients envoyaient un message du type « demain 15h Kemang ? » et quelqu'un répondait s'il était disponible. Deux membres du personnel confirmaient parfois le même créneau à deux clients différents, car la boîte de messages était l'unique source de vérité.
Les week-ends chargés, environ une session sur douze se terminait par un conflit à l'entrée — l'une des parties était renvoyée, remboursée, et se plaignait sur Instagram.
Le client choisit une ville, une agence, une date, une heure et un fond — chaque étape pose une réservation provisoire sur une vraie ligne. Deux téléphones qui tapotent le même créneau à la même seconde : l'un gagne, l'autre voit « déjà pris » et se voit proposer le prochain bloc de 30 minutes disponible.
La confirmation part ensuite par WhatsApp, de sorte que les clients reçoivent une réponse là où ils s'y attendent. Le message est désormais le reçu — pas la réservation.
La moitié des agences sont des studios en box — chaque fond est dans sa propre salle, donc deux fonds signifient deux sessions en parallèle. L'autre moitié sont des studios à fond déroulant — plusieurs fonds accrochés dans une seule salle, mais une seule session peut se dérouler à la fois.
L'ancien site les traitait de façon identique. Des clients réservaient quatre fonds simultanément dans une agence à fond déroulant et arrivaient pour découvrir que c'était impossible.
Chaque agence est taguée multi ou single en base de données. Les studios en box affichent une grille fond×horaire — cliquer sur une cellule, c'est choisir une salle et un horaire en un seul geste. Les studios à fond déroulant proposent un planning partagé unique et un choix de fond séparé, purement esthétique.
Même shell React, mêmes composants, forme de données différente depuis un seul endpoint. Le client n'a jamais besoin de connaître la différence.
○ libre × pris ● sélectionné
Le client fait un virement, prend une capture d'écran de la preuve et l'envoie par WhatsApp. L'administrateur ouvre l'application bancaire, cherche le montant correspondant, répond « ok confirmé » et note le créneau dans le cahier. Cinq minutes par réservation un jour calme, bien plus un samedi.
Si l'administrateur était à déjeuner, le client attendait. Si le client attendait trop longtemps, il annulait.
Confirmation automatique.
Pas de capture d'écran nécessaire.
Pour un administrateur d'agence le samedi entre l'ouverture et midi — la période la plus chargée. La même personne, le même poste, avant et après la refonte.
Passé un samedi entier avec deux administrateurs d'agence. Observé le cahier se remplir, les messages se jongler, l'appli bancaire être rafraîchie. Noté chaque étape. Supprimé tout ce qui n'aurait pas à exister si une base de données existait.
PWA React + Vite, Express + MySQL en backend. Deux modèles de réservation derrière un seul endpoint pour éviter que l'interface ne se bifurque. Intégration QRIS marchand avec fallback webhook pour qu'un réseau instable ne bloque jamais un client en plein paiement.
SPA admin : vue d'ensemble, calendrier de réservations, dépenses, ventes, rapports, paramètres. Déploiement sur une agence d'abord (Kemang), suivi pendant une semaine, puis intégration des autres deux par deux. Les cahiers retirés agence par agence.
Les chiffres ci-dessous proviennent de la base de données en production pour l'agence pilote (Kemang) ainsi que les deux agences connectées par la suite. Les chiffres sur l'ensemble de la chaîne ne seront publiés ici qu'une fois qu'il y aura suffisamment de mois de données réelles.
Six agences dans six villes, un fondateur qui doit pouvoir lire le tableau de bord sur son téléphone en faisant la queue dans un café. Chaque décision a répondu à une question : que se passe-t-il quand le wi-fi d'une agence tombe au milieu d'un samedi chargé ?
Installable depuis l'écran d'accueil. Transitions de pages via Framer Motion. CSS Modules et une palette strictement noir et blanc — les photos apportent la couleur, l'interface reste en retrait.
Une seule base de données, les agences en tant que lignes, le modèle de capacité en enum. Les écritures de créneaux passent par un seul endpoint qui verrouille la ligne pour empêcher deux réservations simultanées de prendre la même cellule.
Code QRIS dynamique par réservation avec un TTL de 15 minutes. Le webhook de règlement libère le créneau ; en cas d'échec du webhook, un poller réconcilie en moins d'une minute. Dans les deux cas, le client voit la même coche.
Pas de codebase admin séparé. La connexion fondateur atterrit dans la mise en page desktop avec sidebar ; la connexion agence atterrit dans une vue mono-agence. RBAC au niveau de l'API, pas de l'interface — naviguer ne peut jamais accorder ce que le serveur n'a pas déjà approuvé.
Appel de cadrage gratuit. On vous dit la chose la moins chère qui règle le problème.
Des projets comme celui-ci s'appuient sur la Core Platform + modules sur mesure — la plupart des systèmes de réservation se situent entre $2 500 et $4 500. Tarifs complets →