Zum Inhalt springen

Fallstudie

Gastronomie-Betrieb

Eine PWA für Dienstplanung, Inventar und Lieferanten-Integrationen eines regionalen Restaurants mit mittlerem Volumen.

Jahr
2025—
Status
live
Rolle
Architekt & Umsetzer
Stack
React Native, Expo SDK 54, Supabase, TypeScript, Playwright

Ein Restaurant mit ~20 Mitarbeitenden organisierte Dienstplanung, Bestellung und Menü von Hand. Diese PWA vereint Dienstplanung, Inventar, Bestellung bei sechs Lieferanten und eine Live-Website in einem System.

Auf einen Blick: Personal, Service, die öffentliche Website, NFC-Taps und sechs Lieferanten speisen alle eine gemeinsame Datenbank, die Dienstplanung, Bestellung und den laufenden Betrieb steuert.
Auf einen Blick

Vorher → nachher

Wöchentliche Dienstplanung
Vorher~2 h WhatsApp-Hin-und-Her
Nachher~30 Min. in der App
Menü-Übersetzung
Vorher~200 € pro Menü, ausgelagert
NachherCent pro Lauf, LLM in der App
Saisonale Menü-Änderung
VorherTage an systemübergreifenden Änderungen
Nachhereine Aktion in der App

~2 h → ~30 Min.

Wöchentliche Dienstplanung

~200 € → Cent

Menü-Übersetzung

seit Dez. 2025

im Produktivbetrieb

Die technische AufschlüsselungAufklappen · ~6 Min.

Das geschäftliche Problem

Ein regionales Restaurant mit mittlerem Volumen organisierte Dienstplanung, Bestellung und seine öffentliche Speisekarte von Hand. Die wöchentliche Personalplanung war etwa zwei Stunden WhatsApp-Hin-und-Her; Lieferantenbestellungen wurden vergessen; die öffentliche Website hinkte der echten Speisekarte hinterher, sodass Gäste mit veralteten Informationen ankamen; und handschriftliche Reservierungen gingen manchmal verloren. Und niemand konnte sehen, wie ein Service tatsächlich getaktet war — wie lange ein Tisch auf Getränke, dann auf Essen wartete — es gab also nichts Konkretes, woran man sich verbessern konnte.

Die Beteiligten: rund zwanzig Mitarbeitende und die Inhaber, die Schichten planen und Bestellungen aufgeben, die Gäste, die buchen und essen, und sechs B2B-Lieferanten, deren Kataloge und Preise sich ständig ändern — keiner davon mit einer brauchbaren API. Die Aufgabe war, all das in ein System zu bringen, dem alle gleichzeitig vertrauen können.

Die Architektur

Eine plattformübergreifende PWA — Web für die Inhaber, Telefone fürs Personal, eine Service-Ansicht — über einem einzigen verwalteten Postgres mit Row-Level Security und Realtime, dazu eine serverseitig gerenderte öffentliche Website, die dieselbe Datenbank nutzt.

Client-Oberflächen — öffentliche Website, Personal-App, Service-Ansicht und NFC-Tisch-Taps — schreiben alle in ein gemeinsames Postgres mit Row-Level Security und Realtime; ein Zeilen-Insert löst gestufte Cache-Updates und E-Mail-/Push-Bestätigungen aus.
Client-Oberflächen — öffentliche Website, Personal-App, Service-Ansicht und NFC-Tisch-Taps — schreiben alle in ein gemeinsames Postgres mit Row-Level Security und Realtime; ein Zeilen-Insert löst gestufte Cache-Updates und E-Mail-/Push-Bestätigungen aus.

Daten werden gestuft zwischengespeichert, je nachdem, wie oft sie sich tatsächlich ändern — Live-Service-Daten aktualisieren in Sekunden, Speisekarten in Tagen — hinter einem Adapter über Browser- und nativem Speicher. Die öffentliche Site rendert aus derselben Datenbank, die die Küche bearbeitet, und sowohl Web als auch App reagieren auf denselben row insert, sodass eine irgendwo eingetragene Reservierung genau eine Bestätigung auslöst.

Die Lieferanten-Schicht war der schwierigste Teil des Aufbaus. Keiner der sechs B2B-Lieferanten bot eine brauchbare API. Einer hatte einen Webshop, dessen Bestell-Endpunkte ich in einen programmatischen Bestellablauf reverse-engineert habe; ein anderer stellte einen halbstrukturierten JSON-Feed bereit; ein dritter hatte nichts außer einem Katalog, der mit Playwright gescrapt wurde. Über diese drei völlig verschiedenen Zugriffsmethoden liegt eine Normalisierungs-Pipeline, die dasselbe Produkt über alle sechs Lieferanten hinweg unscharf abgleicht — sodass ein Preisvergleich Gleiches mit Gleichem vergleicht und eine Bestellung an den jeweils günstigsten der Woche geleitet werden kann. Heterogene, undokumentierte Quellen dazu zu bringen, sich wie ein sauberer Katalog zu verhalten, war der Großteil der Ingenieursarbeit — und das macht aus „Bestellen" statt einer lästigen Pflicht eine Entscheidung.

Sechs B2B-Lieferanten, auf drei Arten erreicht — eine reverse-engineerte Bestell-API, ein halbstrukturierter JSON-Feed und ein Playwright-gescrapter Katalog — speisen eine unscharfe Produkt-Normalisierungsschicht, die dasselbe Produkt über Anbieter hinweg abgleicht, bevor es die gemeinsame Datenbank erreicht.
Sechs B2B-Lieferanten, auf drei Arten erreicht — eine reverse-engineerte Bestell-API, ein halbstrukturierter JSON-Feed und ein Playwright-gescrapter Katalog — speisen eine unscharfe Produkt-Normalisierungsschicht, die dasselbe Produkt über Anbieter hinweg abgleicht, bevor es die gemeinsame Datenbank erreicht.
Lieferanten-QuelleIntegrationsmethodeFragilität
Webshop, keine APIreverse-engineerte Bestell-Endpunktebricht bei einem Site-Redesign
Halbwegs strukturierthalbstrukturierter JSON-Feedbricht bei Schema-Drift
Nur KatalogPlaywright-gescraptbricht bei Markup-Änderung

Eine Änderung, viele Ziele. Hier zahlt sich der Integrations-Bus aus. Eine einzelne Speisekarten-Änderung breitet sich von einer Stelle aus aus: Die öffentliche Website aktualisiert sofort, die hinterlegten Rezepte, die Portions- und Mengenberechnungen steuern, aktualisieren mit, und diese Mengen speisen die reverse-engineerte Lieferanten-Schicht, die die Bestellungen aufgibt. Der saisonale Speisekarten-Wechsel — drei Speisekarten pro Jahr — war früher tagelange manuelle systemübergreifende Bearbeitung; jetzt ist es eine Aktion in der App. Die Menü-Übersetzung läuft denselben Weg: ein LLM in der App übersetzt jede Speisekarte in die anderen Sprachen und ersetzt einen rund 200 € teuren professionellen Auftrag pro Menü durch einen Aufruf für Cent pro Lauf.

Live-Tischstatus über NFC. Das Personal setzt den Live-Zustand eines Tisches — Getränke serviert, Essen serviert, Tisch abgeräumt — durch Antippen eines NFC-Tags am Tisch. Jeder Tap ist ein mit Zeitstempel versehenes Ereignis, das in dasselbe Realtime-Postgres-Backbone geschrieben wird (ein weiterer row insert → notify-Produzent), sodass der Tischzustand sofort über Web-, Personal- und Service-Ansicht geteilt wird.

Die Datenbank ist der Integrations-Bus: Quelle der Wahrheit und Ereignis sind dieselbe Zeile.

Entscheidungen & Abwägungen

Cache-TTL pro Datentyp, nicht eine globale Konstante. Die Frische nach Volatilität zu bemessen, beseitigte sowohl die Veraltungs-Bugs als auch die unnötigen Roundtrips, die ein einzelnes TTL verursachte. Der Preis ist eine Invariante, die man überall halten muss: jeder Schreibvorgang invalidiert seinen Cache-Key.

Eine Website, immer synchron mit der Speisekarte. Die öffentliche Site liest aus derselben Datenbank, die die Küche bearbeitet, sodass eine Speisekarten-Änderung sofort live ist — kein zweites System zu pflegen, keine Verzögerung, über die Gäste stolpern. Die Abwägung: Die öffentliche Site erbt die Form der operativen Datenbank statt eines eigenen, sauberen Content-Modells.

Die Lieferanten reverse-engineeren und die Fragilität in Kauf nehmen. Gegen undokumentierte Webshop-Endpunkte und einen Scraper zu bauen, war der einzige Weg, an Preise zu kommen, die die Lieferanten schlicht nicht veröffentlichen — aber diese Integrationen brechen, sobald ein Lieferant seine Site neu gestaltet. Die Abwägung war explizit: eine brüchige Integration, die einen Live-Preisvergleich liefert, schlägt eine stabile, die es nicht gibt. Jede Quelle ist isoliert und unabhängig validiert, sodass sie, wenn eine bricht, allein degradiert, statt den ganzen Katalog mitzureißen.

NFC-Tap statt In-App-Navigation. Der Live-Status wird durch einen physischen Tap auf ein Tag am Tisch gesetzt, nicht durch das Durchsuchen von App-Bildschirmen. Während eines vollen Service navigiert das Personal nicht durch Menüs — ein reibungsloser Tap wird tatsächlich genutzt, und Akzeptanz, nicht das Datenmodell, ist die echte Grenze. Die Abwägung: NFC-Tags sind physische Infrastruktur, die platziert und gewartet werden muss, und die Daten sind immer nur so gut, wie das Personal daran denkt zu tippen.

Was gebrochen ist

Der übelste Bug war ein nur im Web auftretender Endlos-Spinner beim Fortsetzen (Resume). Der Browser serialisiert die Aktualisierung des Auth-Tokens über ein Lock, und beim Resume wartete ein Datenlesevorgang auf ein Lock, das nie zurückkehrte. Der erste Fix — ein 10-Sekunden-Timeout — ließ den Spinner sich beruhigen statt zu hängen, aber der nächste Lesevorgang scheiterte identisch, weil das Token weiterhin tot war. Der eigentliche Fix aktualisierte die Session vor dem Lese-Sturm nach dem Resume.

Ablauf des Resume-Spinner-Bugs: beim Resume wartet der Datenlesevorgang auf das Auth-Token-Refresh-Lock des Browsers; ein 10-Sekunden-Timeout lässt den Spinner sich beruhigen, aber der nächste Lesevorgang scheitert, weil das Token noch tot ist; der eigentliche Fix aktualisiert die Session vor dem Lese-Sturm nach dem Resume.
Ablauf des Resume-Spinner-Bugs: beim Resume wartet der Datenlesevorgang auf das Auth-Token-Refresh-Lock des Browsers; ein 10-Sekunden-Timeout lässt den Spinner sich beruhigen, aber der nächste Lesevorgang scheitert, weil das Token noch tot ist; der eigentliche Fix aktualisiert die Session vor dem Lese-Sturm nach dem Resume.

Ein Timeout erkauft eine überlebbare UX; nur die Frage „was scheitert beim nächsten Versuch?" führt zur Ursache.

Das Ergebnis

Seit Dezember 2025 im Produktivbetrieb, mit weiterhin neuen Funktionen — und die Erfolge bleiben bewusst getrennt, jeder auf genau das begrenzt, was er verändert hat, statt zu einer Zahl zusammengefasst.

Die Dienstplanung sank von ~2 Stunden WhatsApp-Koordination auf ~30 Minuten pro Woche in der App (diese Zahl betrifft allein die Dienstplanung). Inventar und Bestellerzeugung, früher ein paar Stunden der Woche des Inhabers, werden jetzt vom Personal direkt in der App erledigt — ein Zugewinn an Delegation und Fähigkeit, keine gemessene Zahl. Saisonale Speisekarten-Wechsel (drei Speisekarten pro Jahr) gingen von mehreren Tagen manueller systemübergreifender Arbeit — Website, hinterlegte Rezeptmengen und die Lieferanten-Verknüpfungen, die sie speisen — auf eine einzige Aktion in der App. Die Menü-Übersetzung wechselte von einem professionellen Auftrag zu rund 200 € pro Menü zu einer LLM-Übersetzung in der App für Cent. Reservierungen werden jetzt digital erfasst, sodass keine Buchungen mehr verloren gehen, und die damit verbundenen Gast-Kontaktdaten eröffneten eine Feedback-Schleife, die es auf Papier nicht gab.

Die NFC-Schicht eröffnet etwas, das das Restaurant nie hatte: Weil jeder Status-Tap einen Zeitstempel trägt, werden Service-Zeiten — Zeit bis zum Getränk, Zeit bis zum Essen, Tischwechsel — zum ersten Mal messbar. Es werden noch keine Zahlen behauptet; die Fähigkeit selbst ist das Ergebnis.

Geplant, nicht ausgeliefert: das Live-Signal „Tisch frei" wird die Echtzeit-Reservierungskapazität auf der öffentlichen Website speisen, sodass die Online-Buchung die tatsächliche Verfügbarkeit im Raum widerspiegelt. Die Daten fließen bereits über den Bus — sie in den öffentlichen Buchungsfluss einzubinden, ist der nächste Schritt.