09 — KDS & Kitchen

Kitchen Display, preparables, recipes, fire ticket

CEO Summary

KDS (Kitchen Display System) routes orders to kitchen and expo staff. Essential for restaurants and split-space venues (for example a cinema: prep counter in one room, patrons in the auditorium). Business value: Faster fulfillment, fewer wrong deliveries, runners see where food goes. Key metrics: Order-to-fire time, kitchen throughput, delivery accuracy. If this breaks: Kitchen may not receive orders; manual handoff required.

Overview

KDS = Kitchen Display System — browser route /pos/kitchen (frontend/src/pages/pos/KitchenDisplay.jsx), optional ?station= to match category→station routing from admin. Tickets are stored in the tenant DB (kitchen_tickets) and exposed under /api/kds. Physical kitchen screens can use the same web KDS or, where the Bridge is deployed, the fireTicket action for LAN-side displays.

Floor plan designer + KDS: cinema / dual-room workflow

Operator goal (Vista / NSign-class behaviour): In a movie theatre, Room A might be the concession or prep area where staff assemble trays and ring the sale on POS, while Room B is the auditorium where the guest is seated. Staff in Room A need to see which seat (or row/section) that order belongs to so a runner can find the customer — not only “what to cook” but “where to bring it.”

Why the visual floor plan designer exists: Admin Seating Layouts (/admin/seating-layouts, SeatingLayoutManager.jsx) is the authoritative map of the venue: grid-based editor, cinema-oriented templates (small/medium/large cinema, theater, restaurant), row labels, seat numbers, aisles, stage/screen cues. That layout defines stable seat and table identities (seatId, tableId, labels) that POS attaches to the order.

What the codebase does today: When seat/table metadata is present on a kitchen ticket, the API persists and returns seatId, tableId, tableNumber, and seatNumber (backend/routes/kds.routes.js — both list/ingest paths). The web KDS renders those as readable chips on each ticket (for example “Table 5” and “Seat 12”). That is enough for a dedicated screen in Room A running the normal KDS URL: runners see seat/table text without opening the full floor designer on the line.

Natural extensions (product roadmap, not all built as a single “map on KDS” view yet): A read-only mini floor plan on the expo screen — highlighting the active seat against the same layoutData JSON from GET /api/seating-layouts/:id — would mirror what many cinema POS ecosystems do with signage-style heads. That could be a small SPA view, a Signage–style fullscreen page, or an enhanced KDS mode; the data path is already aligned (layout in tenant DB, seat ids on tickets).

flowchart LR subgraph Design["Admin design-time"] SLM[SeatingLayoutManager] API_SL["/api/seating-layouts"] DB[("Tenant DB seating_layouts")] end subgraph Service["Service order-time"] POS[POS cart seat or table] KT[kitchen_tickets] KDS["KitchenDisplay /pos/kitchen"] end SLM --> API_SL API_SL --> DB POS -->|seat and table fields| KT KT -->|GET /api/kds/orders| KDS DB -.->|layout labels and ids| POS

Enterprise cinema patterns (reference, not vendor specs)

Third-party cinema POS stacks (often discussed under names like Vista, POSitive Cinema / “Indie”, etc.) are proprietary: public docs rarely expose full schemas or source. What follows is the common industry architecture that consultants and LLM summaries converge on — useful as a benchmark for how our platform should evolve, not as a claim that we implement every vendor feature.

PatternTypical in high-end dine-in cinemaGo Past Earth (this repo)
Floor plan as masterEach seat has a stable ID; geometry (grid, SVG, or canvas) served to clients; auditorium / service area groupingseating_layouts.layoutData grid + labels; /api/seating-layouts; cinema-oriented templates in SeatingLayoutManager.jsx
Seat tied to F&BOrder or “virtual check” carries Seat ID + screen/auditorium so F&B is not anonymouskitchen_tickets columns seatId, tableId, tableNumber, seatNumber; POS supplies metadata when building tickets
KDS routingItem category → station (grill, bar, concessions); multi-station split of one orderkdsKitchenRouting.js; admin category→station mapping; ?station= on /pos/kitchen
Prep / expo screenExpo view: final assembly + visual map with seat highlight, colour by SLA (new / in prep / late)Today: lane-based tickets with text table/seat on each card (KitchenDisplay.jsx). Roadmap: overlay on same layout JSON (dedicated view, enhanced KDS mode, or Signage-class fullscreen)
Real-time to screensWebSocket or MQTT from site server to KDS clients; dedicated F&B VLAN vs guest Wi‑FiWeb KDS polls GET /api/kds/orders (interval from localStorage prefs). Bridge WebSocket is used for other LAN/cloud patterns (print, signage push); pushing KDS ticket streams over WS is a plausible upgrade path
Bump / recallPhysical bump bar or touch “done” updates central state; all subscribed heads refreshPOST bump and recall routes on kds.routes.js; clients refetch on poll

Takeaway: The “absolute complete inner workings” of any one vendor product are not publicly knowable end-to-end. The data shape (authoritative seat map + order linkage + station routing + expediter visibility + bump-driven state) is the transferable model — and our codebase already implements the identity and ticket linkage layer; the visual expo map and sub-second push are the main premium-cinema deltas to schedule if you want parity with the experience Gemini/Grok described.

Routes and files

Fire ticket (Bridge)

For on-prem hardware or LAN-attached KDS workflows, the bridge handles fireTicket with orderId, invoiceId, station, items[]. C# reference: KDSService.FireTicketAsync in the bridge repo. Include seat/table fields in the payload when the cloud builds the ticket so downstream displays stay consistent with the web KDS.

Related documentation