A restaurant operating system running on three surfaces at once — a Flutter PoS on Windows terminals and Android handhelds, a white-label Next.js storefront per tenant, and TypeScript microservices behind an nginx gateway on Cloud Run.
0
Surfaces
0
Microservices
0
REST endpoints
0
RBAC roles
=== RESTARAGE POS ===
ROLE: Full Stack Developer & Team Lead
DURATION: Dec 2024 — July 2026
SURFACES: Windows PoS · Android Handheld · Customer PWA
STACK: Flutter · TypeScript · MongoDB · GCP · Stripe
SCOPE: Multi-tenant restaurant operating system
*** THANK YOU ***
DL-00018
Duo Bucket Meal
$182.40
T-00042
Tandori Pan Pizza
$23.63
See It In Action
The PoS experience on a handheld Android terminal — vertical capture, real workflows.
demo video · overview doc · SRS
Three Surfaces, One Platform
Windows checkout terminals, Android handhelds, and customer-facing storefronts — one codebase, three experiences.

Windows PoS
Primary checkout terminal — persistent side navigation, thermal receipt printing over USB/TCP, and full menu/order/billing workflows.
Gateway Routing
pos.restarage.com — custom nginx on Cloud Run, path-based routing to three microservices. Hover a route to trace the request.
pos.restarage.com
nginx gateway :8080
Users, restaurants, branches, subscriptions, Firestore notifications, Stripe Connect
68 REST · 73 GraphQLCatalog, inventory, AI extraction, menu versioning, public PWA reads
19 REST · 51 GraphQLOrders, transactions, PendingCheckout, Stripe web-order webhooks, analytics
32 REST · 5 GraphQLArchitecture Evolution: 7 → 3 Services
Legacy Topology
Current Topology
Retired message brokers to eliminate persistent-connection scaling problems on stateless Cloud Run containers. Cross-service calls are fire-and-forget HTTP; real-time delivery uses Firestore snapshot listeners.
Pay-First Order Lifecycle
A web order traced from checkout tap to kitchen board — no order exists until Stripe confirms payment.
Customer taps checkout
PWA cart → Next.js BFF route
PendingCheckout snapshot
Full cart stored in tps-service — 24h TTL, no Order yet
status: pendingStripe Hosted Checkout
Connect Express destination charge · 2.5% platform fee
checkout.session.completed
tps-service webhook — filtered by metadata.type === 'pwa_checkout'
Order created · Paid
fulfillPendingCheckout → kitchen queue
notifications/internal/dispatch
order.placed → iam-core recipient resolver
Firestore inbox write
users/{uid}/notifications — batch write per role
Flutter PoS listener
Snapshot → ValueNotifier → order board updates
“No kitchen order exists until Stripe confirms payment.”
Batch Upload
≤20 files · ≤25 MB each · JPEG/PNG/WebP/HEIC/PDF
GCS Staging
restaurants/{id}/menu-sources/{draftId}/… · 30-day lifecycle
Vision-LLM
Gemini via OpenRouter · 1–2 images/chunk · PDFs separate
Consolidate JSON
Markdown per chunk → merged structure
Schema Map → Draft
Categories · Meals · Toppings · Sizes — progressive persist
AI writes here only
Progressive schema mapping into categories, meals, toppings, and sizes. Review markers flag uncertain entities.
Invariant gate — AI never touches Live
Owner promotes explicitly
Exactly one LIVE version per restaurant. Make Live triggers cart-safety signal across POS and PWA.
“The AI extraction pipeline shall never read or mutate the Live menu version.” — Bias: false needs review over silent wrong price.Cart Safety
Make Live clears every active cart across POS and PWA — with a casual banner and triple-path detection.
Menu Version
AI import 2026-07-29
Flutter PoS Cart
PWA Cart
Snapshot on restaurants/{id}/menuState/current
GET /menu/versions/live if realtime misses
Detect version change before checkout on reconnect
Target: 100% cart-safety correctness in pilot QA
The Cloud Run Race Condition
When NATS delivered owner:created to every replica simultaneously, three Cloud Run instances raced to create the same restaurant owner.
Three replicas receive owner:created via NATS at-least-once delivery. All converge on one MongoDB write.
Click a replica to run the race
try {
await user.save();
} catch (saveError) {
if (saveError.code === 11000) {
console.log("Duplicate detected. Another replica created the owner first.");
}
}Mitigation Ladder
Graceful E11000 catch on owner creation
(restaurant + role) unique for Owner
SET key locked PX ttl NX
Exactly-once delivery
Flutter PoS Internals
A four-layer GetX architecture — presentation, reactive state, data access, and Hive persistence.
Presentation
lib/components/Pages, dialogs, widgets — role-filtered navigation shell
Reactive State
lib/controllers/GetX controllers — screen state, orchestration, realtime bridges
Data Access
lib/api/CrudApi transport + 11 domain API clients + adapters
Persistence
lib/db/Hive local_db box — 5-min freshness, user-scoped cache keys
Cache-First Reads
DataRepository.get hashes endpoint + port + body + user email → Hive lookup with 5-minute freshness window.
→ Fresh cache: return immediately
→ Stale: background refresh via retry callback
→ Writes: bypass cache, straight to API
Split Realtime Channels
Emulator Routing
Android emulator rewrites localhost → 10.0.2.2 automatically in CrudApi.
Thermal Printer Transports
| Transport | Android | iOS | Windows |
|---|---|---|---|
| USB | ✓ | — | ✓ |
| Bluetooth Classic | ✓ | — | — |
| BLE | ✓ | ✓ | — |
| TCP/Network | ✓ | ✓ | ✓ |
Fork-maintained flutter_pos_printer_platform_image_3 — resolved image v3/v4 dependency conflict after upstream discontinuation.
More From the Product
Branch management, billing, and the add-on marketplace — real screenshots from the live PoS.

Branches

Billing

Store
Customer Storefront
White-label PWA at {slug}.order.restarage.com — host-header tenancy, Stripe Connect, and real-time POS sync from a single Next.js build.
Resolved from Host header
Caching Ladder
Core Web Vitals Targets
Stretch: < 1.8s
Stretch: < 100ms
Stretch: < 0.05
Stretch: < 400ms
Honest note: menu route is not SSR'd yet — client fetch with skeleton. Tiered remediation roadmap documented.
By The Numbers
The engineering footprint — counted up on scroll, printed on thermal paper.
=== ENGINEERING RECEIPT ===
*** END OF RECEIPT ***
Restarage v6 — The AI Vision
From reactive legacy PoS to a proactive AI-driven restaurant operating system.