Portfolio / System Ops / snap

Sechs Filialen, ein Buchungsablauf.
Null Doppelbuchungen.

SNAP ist eine Self-Photo-Studio-Kette in sechs indonesischen Städten. Die alte Website war eine statische Broschüre — Buchungen liefen über WhatsApp-DMs, jede Filiale führte ein eigenes Notizbuch, und etwa jede zwölfte Sitzung endete in einem Konflikt an der Tür. Wir haben den Kundenprozess als PWA neu gebaut und ein zentrales Admin-Dashboard ausgeliefert, das alle sechs Filialen auf einmal zeigt.

KundeSNAP Self-Photo Studio
LeistungenBooking PWA · QRIS · Admin · Reports
Umfang6 Filialen · 2 Studiotypen · 30+ Hintergründe
Zeitraum8 Wochen · 2026 · im Rollout
Was wir gebaut haben

Ein Buchungssystem, das weiß, in welcher Filiale Sie stehen.

Eine Mobile-First-PWA auf Kundenseite, eine Desktop-SPA auf der Admin-Seite, eine API und eine Datenbank darunter. Sechs Module tragen die gesamte Kette — vom Stadtauswahl-Bildschirm, den ein Kunde auf Instagram sieht, bis zur täglichen Abrechnung, die der Filialleiter am Abend bestätigt.

Modul 01

Filial- & Stadtzugang

Sechs Städte, zwölf Filialen, zwei physische Studiotypen. Der Kundenprozess überspringt den Filialschritt automatisch in Städten mit nur einem Studio und wählt das passende Kapazitätsmodell basierend auf dem Standort.

Geo-routedMulti-tenant
Modul 02

Zwei Buchungsmodelle

Box-Studios laufen über eine Hintergrund×Zeit-Matrix — jeder Raum bucht unabhängig. Roll-up-Studios nutzen einen gemeinsamen Zeitplan mit einer rein ästhetischen Hintergrundauswahl. Dieselbe UI-Hülle, zwei unterschiedliche Kapazitätsregeln darunter.

MatrixSingle-slot
Modul 03

QRIS-Autobestätigung

Kunde scannt einen dynamischen QRIS-Code, der Händler-Callback gibt den Slot frei, der Kunde sieht ein Häkchen. Kein Mitarbeiter, der Mobile-Banking überwacht. Keine manuelle „Ist es schon bezahlt?"-Nachricht.

QRISWebhook
Modul 04

Admin-Übersicht

Ein Dashboard für den Inhaber. Heutige Buchungen über sechs Filialen, Umsatz vs. gestern, Ausgaben nach Kategorie, Belegung nach Raum. Von jeder Kachel direkt in die Rohdaten.

Live KPIsDrill-down
Modul 05

Filial-Ops-Konsole

Filialleiter sehen nur ihre Filiale — heutiger Kalender, Walk-in-Slot-Schalter, Ausgabenerfassung, Tagesabschluss-Kassenstand. Rollenbasiert, standardmäßig gesperrt.

RBACDaily close
Modul 06

WhatsApp-Bestätigungen

Buchung bestätigt → WhatsApp-Vorlage mit Slot, Filialadresse und Kalenderlink geht raus. Erinnerung zwei Stunden vorher. Der DM-Thread ist nicht mehr der Ort, wo Buchungen leben — aber noch immer der Ort, wo Kunden Rückmeldung erwarten.

TemplatesReminders
Sechs Filialen · Graustufen werden bei Hover farbig

Eine Produktlinie, eine Identität, sechs Räume.

Snap / Kemang
Snap / Senopati
Snap / Bandung
Snap / Surabaya
Snap / Bali
Snap / Yogya
● Das Problem

Buchungen lebten im WhatsApp-Posteingang.

Jede Filiale hatte eine eigene Admin-Nummer. Kunden schrieben „morgen 15 Uhr Kemang?" und jemand antwortete, wenn er wach war. Zwei Mitarbeiter bestätigten denselben Slot manchmal an zwei verschiedene Kunden, weil der Posteingang die einzige Quelle der Wahrheit war.

An vollen Wochenenden endete ungefähr jede zwölfte Sitzung in einem Konflikt an der Tür — eine Partei wurde abgewiesen, erstattet und wurde auf Instagram laut.

„Wir haben einen Kalender in einer Chat-App betrieben. Es hat funktioniert, bis zwei Nachrichten in derselben Minute ankamen." — Gründer, SNAP
S
Snap Kemang
last seen 11 min ago
Hi! Gibt es morgen um 15 Uhr noch einen Slot?10:42
Ja, bitte 50% Anzahlung10:44
Hey, morgen 15 Uhr, wir sind jetzt 4 Personen10:46
Hi, ich würde gerne morgen um 15 Uhr buchen, noch frei?10:47
Kurz warten, ich prüfe das10:51
Hallo? Ich habe schon überwiesen11:08
??? hallo?11:24
Doppelt gebucht
● Die Lösung

Der Slot ist eine Datenbankzeile, keine Nachricht.

Kunde wählt Stadt, Filiale, Datum, Uhrzeit und Hintergrund — jeder Schritt schreibt eine Reservierung in eine echte Zeile. Zwei Telefone tippen denselben Slot in derselben Sekunde: eines gewinnt, das andere sieht „gerade vergeben" und bekommt den nächsten freien 30-Minuten-Block angeboten.

Die Bestätigung geht danach per WhatsApp raus, damit Kunden dort Rückmeldung bekommen, wo sie es erwarten. Die DM ist jetzt der Beleg — nicht die Buchung.

9:41 ●●●● ◐ ▮▮▮
Snap / Kemang
Sa 14 Feb · Einzelstudio
Schritt 4/6
Zeit wählen · 30 Min. 8 frei
10:00
10:30
11:00
11:30
12:00
12:30
13:00
13:30
14:00
14:30
15:00
15:30
Hintergrund wählen · rein ästhetisch
Rp 120.00013:30 · Blau
Weiter →
● Das zweite Problem

„Hintergründe" bedeuteten zwei verschiedene Dinge.

Die Hälfte der Filialen sind Box-Studios — jeder Hintergrund steht in einem eigenen Raum, also bedeuten zwei Hintergründe zwei parallele Sitzungen. Die andere Hälfte sind Roll-down-Studios — mehrere Hintergründe in einem Raum, aber nur eine Sitzung gleichzeitig möglich.

Die alte Website behandelte sie identisch. Kunden buchten vier Hintergründe zur selben Zeit in einer Roll-down-Filiale und stellten vor Ort fest, dass das nicht möglich war.

Kemang · Sat
13:00 — Adi (4 pax)
13:30 — Sarah ✓
Senopati · Sat
Box A — 1pm Tia
Box B — 1pm Rai
Box C — empty
Bandung
payment? — DP 50
cash 70 — sisanya?
Surabaya
walk-in 2 pax
cust ngantri ←
Bali · Sun
refund 1 booking
double again 😩
Yogya
expense ice 25k
listrik 280k
cleaning 60k
● Die Lösung

Das Kapazitätsmodell liegt am Slot, nicht am Hintergrund.

Jede Filiale ist in der Datenbank als multi oder single markiert. Box-Studios erhalten ein Hintergrund×Zeit-Raster — eine Zelle wählen heißt Raum und Uhrzeit in einem Schritt wählen. Roll-down-Studios erhalten einen gemeinsamen Zeitplan und eine separate Hintergrundauswahl, die rein ästhetisch ist.

Dieselbe React-Hülle, dieselben Komponenten, anderes Datenschema von einem Endpunkt. Der Kunde muss den Unterschied nie kennen.

9:41 ●●●● ◐ ▮▮▮
Snap / Senopati
Sa 14 Feb · Box · 4 Räume
Multi
Raum & Zeit wählen 9 frei
·
12
12:30
13
13:30
14
A
×
×
B
×
C
×
×
D
×

○ frei    × belegt    ● gewählt

Raum B · 13:00Senopati · 30 Min.
Weiter →
● Das dritte Problem

Jemand musste Mobile-Banking überwachen.

Kunde überweist, macht einen Screenshot des Belegs, schickt ihn per WhatsApp. Filial-Admin öffnet die Mobile-Banking-App, sucht den passenden Betrag, antwortet „ok bestätigt" und trägt den Slot ins Notizbuch ein. Fünf Minuten pro Buchung an einem ruhigen Tag, viel länger am Samstag.

War der Admin in der Pause, wartete der Kunde. Wartete der Kunde zu lange, stornierte er.

9:41 ●●●● ◐ ▮▮▮
Mit QRIS bezahlen
Buchung #SNP-2614
Schritt 6/6
Rp 120.000
Snap Kemang · 13:30
14:32 verbleibend

Bestätigt automatisch.
Kein Screenshot nötig.

Warte auf ZahlungAutomatische Erkennung via QRIS-Callback
Live
Vorher & Nachher

So sah ein Samstagmorgen früher aus.

Für einen Filial-Admin am Samstag zwischen Öffnung und Mittag — die geschäftigste Zeitspanne. Dieselbe Person, derselbe Job, vor und nach dem Umbau.

Vorher Sa · 4 Std. Chat-Jonglieren
  • 09:00ÖffnungWhatsApp Web öffnen. 17 ungelesene Chats von Nacht-DMs.
  • 09:20+20 Min.Notizbuch gegen Buchungen vom Vorabend abgleichen. Zwei Slots kollidieren.
  • 10:05+1 Std.Kunde schreibt „Ich habe überwiesen". Mobile-Banking öffnen. Betrag suchen. „Ok" antworten.
  • 10:48+1h 48Zwei Telefone, zwei Kunden, beide wollen 11:30. Einen wählen. Den anderen erstatten.
  • 11:30+2h 30Walk-in kommt. Notizbuch sagt Raum frei. Telefon sagt Raum belegt. Diskussion.
  • 12:55+3h 55Mittagspause wieder verschoben.
~4 Std.
Nachher Sa · 35 Min. Admin
  • 09:00ÖffnungDashboard öffnen. Heutiger Kalender bereits über Nacht befüllt.
  • 09:05+5 Min.WhatsApp-Vorlagen-Thread auf Ausreißer durchsuchen. Keine.
  • 10:00+1 Std.Walk-in kommt. „Walk-in-Slot öffnen" tippen. Kunde zahlt QRIS an der Theke. Slot geloggt.
  • 11:30+2h 30Kurzer Blick auf das Raumbelegungs-Widget. Alle vier Räume laufen. Nichts zu tun.
  • 12:00+3 Std.Mittagspause.
~35 Min. · ~14% von vorher
Wie es entstand

Acht Wochen, drei Rollouts.

01

Wochen 1–2 — das Chaos kartieren

Mit zwei Filial-Admins je einen ganzen Samstag verbracht. Zugeschaut, wie das Notizbuch gefüllt, die Chats jongliert und die Mobile-Banking-App aktualisiert wurde. Jeden Schritt aufgeschrieben. Alles gestrichen, was nicht nötig wäre, wenn eine Datenbank vorhanden wäre.

02

Wochen 3–6 — Kundenprozess bauen

React + Vite PWA, Express + MySQL im Backend. Zwei Buchungsmodelle hinter einem Endpunkt-Schema, damit die UI nicht aufgespalten wird. QRIS-Händlerintegration mit Webhook-Fallback, damit ein instabiles Netz einen Kunden nie mitten in der Zahlung stecken lässt.

03

Wochen 7–8 — Admin + Soft-Launch

Admin SPA: Übersicht, Buchungskalender, Ausgaben, Umsatz, Berichte, Einstellungen. Erst eine Filiale gerollt (Kemang), eine Woche beobachtet, dann den Rest zu zweit ongeboardet. Notizbücher Filiale für Filiale ausgemustert.

Ergebnis · frühe Rollout-Zahlen

Erste Filiale seit ~6 Wochen im System.

Die Zahlen unten stammen aus der Live-Datenbank der Pilotfiliale (Kemang) plus der zwei Filialen, die danach online gingen. Kettenweite Zahlen werden hier erst veröffentlicht, wenn genug Monate echter Daten dahinterstehen.

0
Tür-Konflikte seit Launch
Pilotfiliale · 6 Wochen live · zuvor endete ~jede zwölfte Wochenendsitzung in einem Konflikt.
~85%
Admin-Zeit zurückgewonnen
Samstags-Vormittagsfenster des Filial-Admins von ~4 Std. auf ~35 Min. gesunken — bisher nur Pilotfiliale.
< 6Sek.
Medianer QRIS-Bestätigungs­zeitraum
Vom Scan bis zum „bezahlt"-Callback. War 3–5 Min., solange ein Mensch Mobile-Banking überwachte.
3 / 6
Filialen ongeboardet
Kemang, Senopati, Bandung. Drei weitere im Zwei-Wochen-Takt.
Unter der Haube

Bewusst langweilige Technik.

Sechs Filialen in sechs Städten, ein Gründer, der das Dashboard auf dem Telefon in der Warteschlange im Café lesen können muss. Jede Entscheidung beantwortete eine Frage: Was passiert, wenn das WLAN in einer Filiale mitten im Samstags-Rush ausfällt?

Kunden-Client

React PWA, Mobile-First

Vom Homescreen installierbar. Seitenübergänge via Framer Motion. CSS Modules und eine strikte Schwarz-Weiß-Palette — die Fotos liefern die Farbe, die Chrome bleibt im Hintergrund.

React 18 · Vite · Framer Motion · CSS Modules
Backend

Express + MySQL, ein Mandant

Eine Datenbank, Filialen als Zeilen, Kapazitätsmodell als Enum. Slot-Schreibzugriffe laufen über einen einzelnen Endpunkt, der die Zeile sperrt, damit zwei gleichzeitige Buchungen nicht dieselbe Zelle gewinnen.

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

QRIS dynamisch + Webhook

Pro Buchung ein dynamischer QRIS-Code mit 15-Minuten-TTL. Settlement-Webhook gibt den Slot frei; wenn der Webhook fehlschlägt, gleicht ein Poller binnen einer Minute ab. In jedem Fall sieht der Kunde dasselbe Häkchen.

QRIS dynamic · webhook · poll fallback
Admin

Dieselbe React-App, andere Hülle

Keine separate Admin-Codebasis. Gründer-Login landet im Desktop-Sidebar-Layout, Filial-Login in der Einzelfilial-Ansicht. RBAC auf API-Ebene, nicht in der UI — Klicken kann nie etwas gewähren, was der Server noch nicht genehmigt hat.

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

Buchungs-Posteingang
außer Kontrolle?

Kostenloses Erstgespräch. Wir nennen Ihnen die günstigste Lösung.

Systeme wie dieses laufen auf der Core Platform + Custom-Modulen — die meisten Buchungssysteme liegen zwischen $2.500 und $4.500. Alle Preise →