Portfolio / System Ops / snap

Sei sedi, un solo flusso di prenotazione.
Zero doppie prenotazioni.

SNAP è una catena di self-photo studio in sei città indonesiane. Il vecchio sito era una brochure statica — le prenotazioni arrivavano via DM su WhatsApp, ogni sede gestiva il proprio quaderno, e circa una sessione su dodici finiva con uno scontro alla porta. Abbiamo ricostruito il flusso cliente come PWA e consegnato un unico pannello di controllo che vede tutte e sei le sedi in un colpo solo.

ClienteSNAP Self-Photo Studio
ScopeBooking PWA · QRIS · Admin · Report
Scala6 sedi · 2 tipi di studio · 30+ fondali
Tempi8 settimane · 2026 · in rollout
Cosa abbiamo costruito

Un sistema di prenotazione che sa in quale sede si trova il cliente.

Una PWA mobile-first lato cliente, una SPA desktop lato admin, un'unica API e un unico database sotto. Sei moduli reggono l'intera catena — dalla schermata città che il cliente vede su Instagram al riepilogo giornaliero che il responsabile di sede conferma a fine turno.

Modulo 01

Sedi & portali città

Sei città, dodici sedi, due archetipi di studio fisico. Il flusso cliente salta automaticamente la scelta della sede nelle città con un solo studio e instrada il modello di capienza corretto in base alla location.

Geo-routedMulti-tenant
Modulo 02

Due modelli di prenotazione

Gli studio box utilizzano una matrice fondale×orario — ogni stanza si prenota in modo indipendente. Gli studio a rullo hanno un unico calendario condiviso con scelta del fondale puramente estetica. Stessa struttura UI, due regole di capienza diverse sotto.

MatrixSingle-slot
Modulo 03

QRIS auto-conferma

Il cliente scansiona un codice QRIS dinamico, il callback del merchant libera lo slot, il cliente vede la spunta. Nessuno staff che controlla il m-banking. Nessun messaggio manuale "ha pagato?".

QRISWebhook
Modulo 04

Panoramica admin

Un solo dashboard per il fondatore. Prenotazioni odierne su tutte e sei le sedi, vendite rispetto a ieri, spese per categoria, occupazione per stanza. Da qualsiasi riquadro si scende fino alle righe grezze.

Live KPIsDrill-down
Modulo 05

Console operativa di sede

I responsabili di sede vedono solo la propria sede — calendario odierno, attivazione slot walk-in, registro spese, conteggio cassa a fine giornata. Basato sui ruoli, bloccato per impostazione predefinita.

RBACDaily close
Modulo 06

Conferme WhatsApp

Prenotazione confermata → parte un messaggio WhatsApp precompilato con lo slot, l'indirizzo della sede e un link al calendario. Reminder due ore prima. Il thread DM non è più dove vivono le prenotazioni, ma è ancora dove i clienti si aspettano una risposta.

TemplatesReminders
Sei sedi · il grigio diventa colore al passaggio del mouse

Una linea di prodotto, un'identità, sei stanze.

Snap / Kemang
Snap / Senopati
Snap / Bandung
Snap / Surabaya
Snap / Bali
Snap / Yogya
● Il problema

Le prenotazioni vivevano in una inbox di WhatsApp.

Ogni sede aveva il proprio numero admin. I clienti scrivevano "domani alle 15 a Kemang?" e qualcuno rispondeva se era sveglio. Due addetti a volte confermavano lo stesso slot a due clienti diversi, perché l'inbox era l'unica fonte di verità.

Nei fine settimana di punta circa una sessione su dodici finiva con uno scontro alla porta — una parte veniva rimbalzata, rimborsata e diventava rumorosa su Instagram.

«Stavamo gestendo un calendario dentro un'app di chat. Funzionava finché non arrivavano due messaggi nello stesso minuto.» — fondatore, SNAP
S
Snap Kemang
ultima visita 11 min fa
Ciao! C'è uno slot domani alle 15?10:42
Sì, 50% di acconto prego10:44
Ehi, domani alle 15 siamo in 410:46
Ciao, vorrei prenotare anche io le 15 di domani, è ancora libero?10:47
Un attimo, controllo10:51
Pronto? Ho già fatto il bonifico11:08
??? ciao?11:24
Doppia prenotazione
● La soluzione

Lo slot è una riga nel database, non un messaggio.

Il cliente sceglie una città, una sede, una data, un orario e un fondale — ogni passaggio scrive un blocco su una riga reale. Due telefoni che premono lo stesso slot nello stesso secondo: uno vince, l'altro vede "appena occupato" e si vede proporre il prossimo blocco libero da 30 minuti.

La conferma arriva poi via WhatsApp, così i clienti ricevono risposta dove si aspettano. Il DM è ora la ricevuta — non la prenotazione.

9:41 ●●●● ◐ ▮▮▮
Snap / Kemang
Sab 14 Feb · studio singolo
Passo 4/6
Scegli un orario · 30 min 8 liberi
10:00
10:30
11:00
11:30
12:00
12:30
13:00
13:30
14:00
14:30
15:00
15:30
Scegli un fondale · solo estetico
Rp 120.00013:30 · Blu
Continua →
● Secondo problema

«Fondali» significava due cose diverse.

Metà delle sedi sono studio box — ogni fondale occupa una stanza propria, quindi due fondali equivalgono a due sessioni parallele. L'altra metà sono studio a rullo — più fondali appesi in un'unica stanza, ma una sola sessione per volta.

Il vecchio sito li trattava in modo identico. I clienti prenotavano quattro fondali contemporaneamente in una sede a rullo e arrivavano scoprendo che non potevano tenersi tutti.

Kemang · Sab
13:00 — Adi (4 pax)
13:30 — Sarah ✓
Senopati · Sab
Box A — 13:00 Tia
Box B — 13:00 Rai
Box C — libero
Bandung
pagato? — acc. 50
cash 70 — resto?
Surabaya
walk-in 2 pax
cust in fila ←
Bali · Dom
rimborso 1 prenotaz.
doppia ancora 😩
Yogya
spese ghiaccio 25k
listrik 280k
pulizie 60k
● La soluzione

Il modello di capienza vive sullo slot, non sul fondale.

Ogni sede è contrassegnata multi o single nel database. Gli studio box ottengono una griglia fondale×orario — scegliere una cella significa scegliere una stanza e un orario in un solo gesto. Gli studio a rullo ottengono un unico calendario condiviso e una scelta separata del fondale, puramente estetica.

Stessa struttura React, stessi componenti, forma dei dati diversa da un unico endpoint. Il cliente non deve mai sapere la differenza.

9:41 ●●●● ◐ ▮▮▮
Snap / Senopati
Sab 14 Feb · box · 4 stanze
Multi
Scegli stanza & orario 9 liberi
·
12
12:30
13
13:30
14
A
×
×
B
×
C
×
×
D
×

○ libero    × occupato    ● selezionato

Stanza B · 13:00Senopati · 30 min
Continua →
● Terzo problema

Qualcuno doveva tenere d'occhio il m-banking.

Il cliente fa il bonifico, cattura lo schermo come prova, la invia su WhatsApp. L'admin della sede apre l'app di m-banking, cerca l'importo corrispondente, risponde «ok confermato» e segna lo slot nel quaderno. Cinque minuti per prenotazione nelle giornate tranquille, molto di più il sabato.

Se l'admin era a pranzo, il cliente aspettava. Se aspettava troppo, annullava.

9:41 ●●●● ◐ ▮▮▮
Paga con QRIS
Prenotazione #SNP-2614
Passo 6/6
Rp 120,000
Snap Kemang · 13:30
14:32 left

Conferma automatica.
Nessuno screenshot necessario.

In attesa di pagamentorilevamento auto via QRIS callback
Live
Prima & dopo

Com'era un sabato mattina.

Per un admin di sede il sabato tra l'apertura e mezzogiorno — la fascia più intensa. Stessa persona, stesso lavoro, prima e dopo il rifacimento.

Prima Sab · 4h tra le chat
  • 09:00aperturaApri WhatsApp Web. 17 chat non lette dai DM notturni.
  • 09:20+20 minConfronta il quaderno con le prenotazioni della sera prima. Due slot in conflitto.
  • 10:05+1 oraIl cliente scrive «ho fatto il bonifico». Apri il m-banking. Cerca l'importo. Rispondi «ok».
  • 10:48+1h 48Due telefoni, due clienti, entrambi vogliono le 11:30. Scegli uno. Rimborsa l'altro.
  • 11:30+2h 30Arriva un walk-in. Il quaderno dice che la stanza è libera. Il telefono dice che è prenotata. Discussione.
  • 12:55+3h 55Pranzo rimandato ancora.
~4 hr
Dopo Sab · 35 min di gestione
  • 09:00aperturaApri il dashboard. Il calendario odierno è già stato popolato in automatico durante la notte.
  • 09:05+5 minScorri il thread WhatsApp dei template in cerca di anomalie. Nessuna.
  • 10:00+1 oraArriva un walk-in. Premi «apri slot walk-in». Il cliente paga con QRIS al bancone. Slot registrato.
  • 11:30+2h 30Dai un'occhiata al widget di occupazione stanze. Tutte e quattro le stanze in funzione. Niente da fare.
  • 12:00+3 orePranzo.
~35 min · ~14% di prima
Come è nato

Otto settimane, tre rollout.

01

Settimane 1–2 — mappare il caos

Un sabato intero ciascuno con due admin di sede. Abbiamo osservato il quaderno che si riempiva, le chat che si accavallavano, il m-banking che veniva aggiornato di continuo. Ogni passaggio annotato. Tutto ciò che non serviva se esistesse un database, eliminato.

02

Settimane 3–6 — costruire il flusso cliente

PWA React + Vite, Express + MySQL sul backend. Due modelli di prenotazione dietro un'unica forma di endpoint così la UI non si sdoppia. Integrazione merchant QRIS con fallback webhook affinché una rete instabile non lasci mai un cliente a metà del pagamento.

03

Settimane 7–8 — admin + soft launch

SPA admin: panoramica, calendario prenotazioni, spese, vendite, report, impostazioni. Prima attivazione su una sola sede (Kemang), monitorata per una settimana, poi le altre due alla volta. I quaderni ritirati sede per sede.

Risultati · dati delle prime settimane

Prima sede sul sistema da ~6 settimane.

I numeri qui sotto provengono dal database live della sede pilota (Kemang) più le due sedi andate online in seguito. I dati sull'intera catena verranno pubblicati solo quando ci saranno abbastanza mesi di dati reali alle spalle.

0
Scontri alla porta dal lancio
Sede pilota · 6 settimane live · in precedenza ~1 sessione su 12 nei weekend finiva in conflitto.
~85%
Tempo admin recuperato
La finestra pre-mezzogiorno del sabato dell'admin di sede è scesa da ~4 ore a ~35 minuti — solo sede pilota, per ora.
< 6sec
Conferma QRIS mediana
Dalla scansione al callback «pagato». Prima erano 3–5 min mentre un operatore controllava il m-banking.
3 / 6
Sedi attivate
Kemang, Senopati, Bandung. Altre tre in arrivo con un ritmo di una ogni due settimane.
Sotto il cofano

Tecnologia noiosa, di proposito.

Sei sedi in sei città, un fondatore che deve poter leggere il dashboard dal telefono in fila al bar. Ogni decisione ha risposto a: cosa succede se il wi-fi di una sede cade nel pieno del sabato?

Client utente

React PWA, mobile-first

Installabile dalla schermata Home. Transizioni di pagina via Framer Motion. CSS Modules e palette strettamente bianco-nero — le foto portano il colore, il chrome se ne sta fuori dai piedi.

React 18 · Vite · Framer Motion · CSS Modules
Backend

Express + MySQL, tenant singolo

Un unico database, sedi come righe, modello di capienza come enum. Le scritture degli slot passano per un unico endpoint che blocca la riga per impedire a due prenotazioni simultanee di vincere la stessa cella.

Node 20 · Express · MySQL 8 · row-level locks
Pagamenti

QRIS dinamico + webhook

Codice QRIS dinamico per prenotazione con TTL di 15 minuti. Il webhook di liquidazione libera lo slot; se il webhook fallisce, un poller riconcilia entro un minuto. In entrambi i casi il cliente vede la stessa spunta.

QRIS dynamic · webhook · poll fallback
Admin

Stessa app React, shell diversa

Nessuna codebase admin separata. Il login del fondatore porta al layout desktop con sidebar; il login di sede porta a una vista a sede singola. RBAC all'API, non all'UI — navigare nell'interfaccia non potrà mai darti qualcosa che il server non ha già approvato.

RBAC · server-checked routes · desktop SPA
Successivo → GhostKitchen

Inbox prenotazioni
fuori controllo?

Una chiamata esplorativa gratuita. Le diremo la cosa più semplice che risolve il problema.

Sistemi come questo girano su Core Platform + moduli personalizzati — la maggior parte dei sistemi di prenotazione si colloca tra $2.500 e $4.500. Prezzi completi →