33 · QSR & pizzeria vertical pack

How independent pizzerias and quick-service restaurants run on the same Business OS — POS, KDS, inventory, payments, and one shared storefront — without a forked “pizza product.” Markdown twin: docs/PLATFORM-VERTICAL-QSR.md.

Phases 0–2 · 3a ingest · 3b brand pack Storefront card · Crypto schema · Franchise Compose, don’t fork One storefront · retail | restaurant mode Updated 2026-07-25
Product decision There is not a separate pizza-only website product. The existing multi-tenant storefront gains a businessMode (retail | restaurant). Restaurant mode adds pickup/delivery, configurators, and kitchen/delivery handoff after pay.

1. Goal

Pack providesNot the pack
Order type / channel / promise / guest Generic barcode-only retail POS
Pizza / BYO product configurator Full franchise ERP
Station graph + expo whole-order ready Third-party delivery fleet by itself
Delivery dispatch board Separate pizza.com host
Shared storefront restaurant mode Forked eatery-only storefront codebase

2. Day-in-the-life flow

flowchart LR
  POS[Modern POS
fulfillment + builder + deals] SF[Storefront
restaurant mode] CART[Cart metadata
orderType · channel · guest] KDS[Kitchen tickets
orderId = cart id] EXPO[Expo board
all stations DONE] DEL[Delivery board
prep → ready → out] INV[Inventory burn
SKU or configurator] POS --> CART SF --> CART CART --> KDS CART --> INV KDS --> EXPO EXPO --> DEL CART -->|orderType delivery| DEL

3. Order fulfillment (POS cart metadata)

FieldValues / purpose
orderTypedine_in · carryout · delivery · drive_thru
orderChannelcounter · phone · online · kiosk · third_party
guestName / phoneCarryout & delivery contact
addressLine* / cityDelivery address
promiseMinutesQuoted wait (KDS chip)
deliveryFeeCents / notesDispatch ops

UI: Modern POS → Order fulfillment bar. API: PATCH /api/pos/carts/:id/metadata. Codes: backend/utils/orderFulfillment.js.

4. Product configurator (pizza builder)

  • Catalog item metadata.configurator (sizes, crusts, sauces, toppings, half & half).
  • Admin: /admin/catalog/configurator — attach builder + inventory Inv ID / SKU / burn qty.
  • POS / storefront: ProductConfiguratorDialog → line name, base + modifierCents, mods[].
  • Mixed carts: configured pizza plus normal inventory SKUs in one cart is supported.

5. Kitchen · Expo · bake timers

PieceBehavior
orderIdCart id — multi-station tickets group for expo
StationsCategory routing; Apply pizzeria stations (pizza→make, drinks→bar)
ExpoGET /api/kds/expo — ready when all stations DONE; Bag handoff
BakeLine bakeSeconds (default 12m pizza); countdown on KDS card
UI/pos/kitchen — lanes + Expo tab (keyboard 5)

See also 15 · Floor · KDS · Beacon.

6. Delivery dispatch

Status: quotedprepreadyoutdelivered (+ cancelled).

  • UI: /pos/delivery (alias /pos/dispatch)
  • Table: delivery_orders on tenant main
  • Auto: send-to-kitchen on delivery cart → prep; Expo bag → ready
  • QA: Admin Tools → Seed delivery board
MethodPath
GET/api/delivery/board
POST/api/delivery/from-cart/:cartId
POST/api/delivery/orders/:id/status
POST/api/delivery/orders/:id/assign

7. Deals / combos (pilot)

DealRule
2 Large Pizzas$3 off for 2+ large pizzas
Pizza + Drink$1.50 per pizza+drink pair
Carryout 5%5% off carryout (max $5)

GET /api/pos/deals · POST /api/pos/carts/:id/deals/apply · POS button Apply deals.

8. Shared storefront (not a pizza site)

ModeUse
retailMerch / shipping e‑commerce
restaurantPickup/delivery, builders, KDS + delivery after pay
  • Admin → Storefront Settings → Business mode
  • Fields: businessMode, verticalConfig on storefront_settings
  • Guest: /{tenant}/store · paid handoff via storefrontKitchen.bridge.js

See 18 · Customers & Storefront.

9. Inventory on finalize

Line typeBehavior
Stocked catalog / inventory SKUDecrement finished good when tracking on
Recipe consumable (Sous Chef)Burn recipe ingredients
Configured pizza with Inv ID/SKU on optionsBurn size/crust/sauce/toppings (half burn for halves)
Unlinked demo “Build a pizza”Kitchen only — no stock change

Util: backend/utils/configuratorInventory.js. Admin: Catalog → Configurator → Inv ID / SKU / burn. Detail: 25 · Inventory.

10. API map (quick)

AreaEndpoints
Fulfillment PATCH /api/pos/carts/:id/metadata
Deals GET /api/pos/deals · POST .../deals/apply
Kitchen POST .../send-to-kitchen · GET /api/kds/orders · bump / expo / bag
Delivery /api/delivery/board · status · assign
Admin KDS POST /api/admin/kds/routing/preset/pizzeria
Storefront /api/storefront/:slug/* (config includes businessMode)
Aggregators POST /api/integrations/orders · GET .../by-ref/:source/:id

11. Aggregator ingest (Phase 3a)

Generic third-party order webhook → same cart / KDS / delivery spine. Partner-specific DoorDash/Uber adapters and menu sync are still later.

EndpointPurpose
POST /api/integrations/ordersIngest (idempotent on source + externalOrderId)
GET /api/integrations/orders/by-ref/…Lookup prior ingest
GET /api/integrations/healthAuth / tenant probe

Auth: staff session or X-Api-Key. Cart metadata: channel=aggregator, orderChannel=third_party, channelRef. Table: aggregator_order_refs. DoorDash / Uber-shaped JSON is auto-mapped. Optional HMAC: X-Integrations-Signature (+ tenant secret or env). Smoke: npm run smoke:qsr in app/backend.

Kitchen Displays includes an oven handoff toggle (ovenHandoffEnabled). Mobile POS supports seating when the device has the visualizer enabled.

Brand pack (3b): GET/PUT /api/admin/franchise · Storefront Settings → multi-unit brand metadata for this tenant only (locations under one business — not cross-tenant HQ menu push). Storefront card tries the payment orchestrator; ?demo=1 for simulate.

12. Operator pilot checklist

  1. Kitchen Displays → Apply pizzeria stations · set oven handoff on/off.
  2. Catalog → Configurator → BYO pizza + link toppings to inventory.
  3. Optional: /admin/deals — custom fixed $ off + toggle builtins.
  4. POS or Mobile POS → Build pizza + soda → fulfillment / seating → Apply deals → pay / send kitchen.
  5. If ingredients short → add is blocked with shortfall message.
  6. KDS → bump make → auto oven ticket (if enabled) → bump oven → Expo → Bag.
  7. If delivery → ZIP for zone fee · /pos/delivery → assign driver → Out → Delivered.
  8. Storefront Settings → Restaurant mode + zone rows → guest order on /{tenant}/store.
  9. Tools → QSR smoke check (deals, burns, zones, oven setting, sample aggregator order, make ticket).
  10. Optional: POST /api/integrations/orders with a DoorDash-like payload for channel testing.

13. File anchors

AreaPath
Design MDdocs/PLATFORM-VERTICAL-QSR.md
Fulfillmentbackend/utils/orderFulfillment.js
Configurator invbackend/utils/configuratorInventory.js
Dealsbackend/utils/posDeals.js
Expobackend/utils/kdsExpo.js
Deliverybackend/services/deliveryDispatch.service.js · routes/delivery.routes.js
Aggregatorbackend/services/aggregatorIngest.service.js · routes/aggregator.routes.js
Storefront kitchenbackend/services/storefrontKitchen.bridge.js
POS UIModernPOS.jsx · MobilePOS.jsx · fulfillment / seating
KDS UIKitchenDisplay.jsx
Dispatch UIDeliveryDispatch.jsx
Storefront UIStorefront.jsx