Skip to main content

EP-022: KDS & Self-Service Kiosk

Business Objective​

Kitchen Display Systems eliminate paper KOTs -- orders appear on-screen instantly, color-coded by age, ensuring kitchen staff never lose a ticket and managers can spot bottlenecks at a glance. Average food delivery time drops 20-30% when kitchens move from paper to KDS. Self-service kiosks reduce front desk queuing during peak check-in (2-4 PM) by allowing guests to check themselves in, order room service, and view their folio -- freeing front desk agents for high-touch guest interactions and complex operations. For Indian hotels targeting international and tech-savvy domestic travelers, kiosks signal a modern, efficient property.

Audience​

  • Primary: Kitchen Staff (chefs, line cooks, expeditors), Guests (kiosk self-service)
  • Secondary: F&B Managers (KDS monitoring), Front Desk Managers (kiosk oversight), IT Admin (device provisioning)

Scope​

In Scope​

Kitchen Display System (KDS):

  • Real-time KOT display via Socket.io connection to POS service
  • Station filtering (grill, salad, dessert, bar, etc.) -- each physical screen shows only its station's orders
  • Order age tracking with color-coded urgency: green (< 5 min), yellow (5-10 min), red (> 10 min)
  • Bump to complete (tap order card to mark done, removes from display)
  • Rush/priority indicator for VIP or time-sensitive orders
  • Audio alerts for new orders (configurable sound per station)
  • Multi-station view (split screen showing 2 stations simultaneously for expeditors)
  • KOT reprint via connected ESC/POS thermal printer
  • Order recall (view recently bumped orders to handle disputes/re-fires)

Self-Service Kiosk:

  • Guest check-in flow: scan ID document -> find reservation -> verify identity -> assign room -> dispense key card
  • Room service ordering: browse F&B menu -> add items to cart -> confirm order -> charge to room
  • Folio/bill viewing: view current charges -> make payment (UPI/card via integrated terminal)
  • Touchscreen-optimized interface with large tap targets (min 48px)
  • Multilingual support (English, Hindi)
  • Accessibility mode (high contrast, larger fonts, screen reader hints)

Out of Scope​

  • KDS mobile version (KDS is designed for wall-mounted screens, not handheld)
  • Kiosk check-out flow (requires folio settlement complexity beyond MVP)
  • Kiosk concierge services (restaurant reservations, activity booking -- future)
  • Physical hardware procurement (ID scanners, key encoders, payment terminals, kiosk enclosures)

Current Implementation Status​

  • KDS Electron App (05-hmp-kds-kiosk/packages/kds/): Full renderer with components -- OrderBoard (grid layout of active orders), OrderCard (individual order with items, table number, time), Timer (elapsed time with color transitions), StationFilter (dropdown/button bar for station selection), BumpButton (tap to complete), AlertBanner (visual alert for new/aged orders), PrintButton and OrderItem. Main process includes ESC/POS formatter (escpos-formatter.ts) and printer service (printer.service.ts). Preload bridge for IPC. Zustand store (likely in store/). Unit tests for OrderCard and Timer. Socket.io connection for real-time order streaming.
  • Kiosk Electron App (05-hmp-kds-kiosk/packages/kiosk/): Renderer with components -- ReservationLookup, GuestVerification, IdScanner, RoomSelection, KeyDispenser, PaymentScreen, ConfirmationScreen, LanguageSelector. Hardware mock layer in main process (idScanner.mock.ts, keyEncoder.mock.ts, paymentTerminal.mock.ts, printer.mock.ts). i18n directory for multilingual support. Preload bridge. Store directory.
  • Shared Package (05-hmp-kds-kiosk/packages/shared/): Shared types and utilities between KDS and kiosk.
  • Build: Monorepo with Vitest config. ESLint + Prettier. TypeScript with base config.

Gap Analysis​

  • KDS Audio Alerts: The AlertBanner component provides visual alerts only. No audio playback for new orders. The Web Audio API or Electron shell.beep() is not integrated. Kitchen environments are noisy -- visual-only alerts are insufficient.
  • KDS Multi-Station View: StationFilter allows selecting one station at a time. An expeditor needs to see 2-3 stations simultaneously in a split-screen layout to coordinate plating. This view does not exist.
  • KDS Order Recall: Once an order is bumped (completed), it disappears from the board. There is no way to recall a recently completed order if a dish needs to be re-fired or a dispute arises. A "recall" drawer or history panel is needed.
  • KDS Printer Integration: ESC/POS formatter and printer service exist in the main process, but the connection to a physical or network thermal printer is not tested. The PrintButton triggers IPC to main, but the actual print flow (discover printer, send formatted data, handle errors) may not be end-to-end functional.
  • Kiosk Backend Integration: All kiosk components exist with mock hardware adapters, but the actual API calls to backend services (reservation lookup, room assignment, folio fetch, payment processing) are using mock data. The kiosk does not call real backend endpoints.
  • Kiosk Hardware Integration: Mock adapters exist for ID scanner, key encoder, payment terminal, and receipt printer. Actual hardware SDK integration (e.g., Morpho ID scanner, Vingcard key encoder, Pine Labs payment terminal) requires hardware-specific drivers that are not implemented.
  • Kiosk Accessibility: LanguageSelector exists (en/hi), but accessibility mode (high contrast, large fonts, screen reader) is not implemented.
  • Kiosk Room Service Ordering: The kiosk components focus on check-in flow. Room service ordering (menu browse, cart, room charge) is not built.

User Stories​

Story IDTitlePriorityPointsStatusSprint
US-022-001KDS Real-Time Order Display with Station FilteringP08Built4
US-022-002KDS Order Age Tracking & Color-Coded UrgencyP03Built4
US-022-003KDS Bump to CompleteP03Built4
US-022-004KDS Audio Alerts for New OrdersP13Not Started7
US-022-005KDS Multi-Station Expeditor ViewP25Not Started9
US-022-006KDS KOT Reprint & Order RecallP15Partial8
US-022-007Kiosk Self-Service Check-In FlowP013Partial6
US-022-008Kiosk Room Service OrderingP18Not Started8
US-022-009Kiosk Multilingual & AccessibilityP15Partial7

Dependencies​

  • EP-008 (POS & F&B): KDS receives orders from the POS service via Socket.io/Kafka events. Menu data for kiosk room service comes from POS.
  • EP-003 (Reservations): Kiosk check-in requires reservation lookup and room assignment APIs.
  • EP-010 (Billing & Folio): Kiosk bill viewing and payment require folio service APIs.
  • EP-001 (Auth & Access): Kiosk may use a service account or guest token for API access.
  • EP-020 (Infrastructure): Electron app distribution, network configuration for Socket.io in hotel LAN.
  • Hardware Vendors: ID scanner SDK (Morpho/3M), key encoder SDK (Vingcard/ASSA ABLOY), payment terminal SDK (Pine Labs/Razorpay POS).

Acceptance Criteria (Epic Level)​

  • KDS displays new orders within 2 seconds of KOT submission from POS/mobile app
  • Kitchen staff can filter orders by station and bump completed orders with a single tap
  • Audio alert plays for every new order and escalates for orders aging beyond 10 minutes
  • Kiosk allows a guest to check in (ID scan to key card dispense) in under 3 minutes
  • Kiosk supports English and Hindi with runtime language switching
  • Kiosk handles hardware failures gracefully (e.g., key encoder offline -> direct to front desk)
  • Both KDS and kiosk run as Electron apps on dedicated hardware (KDS: wall-mounted display, kiosk: touchscreen terminal)

KPIs / Success Metrics​

  • KDS order-to-display latency: < 2 seconds
  • Average food preparation time (order to bump): 15% reduction after KDS adoption
  • KDS bump accuracy: > 99% (orders not re-fired unnecessarily)
  • Kiosk check-in completion rate: > 70% of attempts (remainder redirected to front desk)
  • Kiosk average check-in time: < 3 minutes
  • Kiosk uptime: > 99% during operating hours (6 AM - 11 PM)
  • Kiosk language usage: track en vs hi selection for localization investment decisions

Detailed User Stories​

US-022-001: KDS Real-Time Order Display with Station Filtering​

As a kitchen line cook, I want to see only the orders for my station (e.g., grill) appear on the display in real-time, So that I can focus on my prep without sifting through orders meant for other stations.

Priority: P0 | Points: 8 | Sprint: 4 | Status: Built

Implementation Status​

The KDS Electron app has a fully functional OrderBoard component that renders OrderCard components in a grid layout. Each OrderCard shows table number, server name, order items (via OrderItem component), and elapsed time (via Timer component). The StationFilter component allows selecting a station (all, grill, salad, dessert, bar) and filters the displayed orders accordingly. Socket.io connection receives real-time order events from the backend POS service. Zustand store manages order state, station filter, and bump actions. Unit tests exist for OrderCard and Timer components.

Acceptance Criteria​

Scenario: New KOT appears on KDS within 2 seconds
Given the KDS is running on the grill station display, connected via Socket.io
And a server submits a new order with 2 grill items (Tandoori Chicken, Seekh Kebab) from the F&B mobile app
When the POS service emits a "kot.created" Socket.io event
Then a new OrderCard appears on the KDS grid within 2 seconds
And the card shows: Table 7, server "Rahul", items with quantities, and timer starting at 0:00
And the card appears at the rightmost position (newest orders on right)

Scenario: Station filter shows only relevant orders
Given the KDS has 8 active orders across 4 stations (grill, salad, dessert, bar)
When the cook selects "Grill" from the StationFilter
Then only the 3 grill-station orders are displayed on the board
And orders for salad, dessert, and bar are hidden
And the filter selection persists across new incoming orders

Scenario: Order with items spanning multiple stations shows partial view
Given an order has 2 grill items and 1 salad item
When the grill station KDS displays this order
Then only the 2 grill items are shown on the card
And a badge indicates "1 more item at other stations"
And the salad station KDS shows only the salad item from the same order

US-022-002: KDS Order Age Tracking & Color-Coded Urgency​

As a kitchen expeditor, I want to see at a glance which orders are taking too long via color-coded timers, So that I can escalate aging orders before guests complain.

Priority: P0 | Points: 3 | Sprint: 4 | Status: Built

Implementation Status​

The Timer component calculates elapsed time from order creation and renders with color-coded backgrounds: green (< 5 minutes), yellow (5-10 minutes), red (> 10 minutes). The OrderCard integrates the Timer and applies the color to the card border/header. Color thresholds are currently hardcoded. Unit test for Timer validates color transitions at threshold boundaries.

Acceptance Criteria​

Scenario: Timer transitions through color thresholds
Given an order was received at 12:00:00 and the current time is 12:04:30
When the KDS renders the order card
Then the timer shows "4:30" with a green background
And at 12:05:00, the timer transitions to yellow background with "5:00"
And at 12:10:00, the timer transitions to red background with "10:00"
And the transition includes a brief pulse animation to draw attention

Scenario: All red orders are visually prominent
Given 6 orders are on the board: 2 green, 3 yellow, 1 red
When the expeditor scans the display
Then the red order card has a bold red border, pulsing timer, and is visually distinct from yellow and green cards
And the AlertBanner at the top shows "1 order overdue (> 10 min)"

Scenario: Rush order has distinct priority indicator
Given a VIP table (Table 1) places an order marked as "Rush" by the server
When the order appears on the KDS
Then a "RUSH" badge is displayed on the OrderCard in a contrasting color (e.g., magenta)
And the order is positioned at the leftmost position (highest priority, regardless of age)

US-022-003: KDS Bump to Complete​

As a kitchen line cook, I want to tap an order card to mark it as complete and remove it from my display, So that I can focus on remaining orders and the expeditor knows the dish is ready for plating.

Priority: P0 | Points: 3 | Sprint: 4 | Status: Built

Implementation Status​

The BumpButton component is rendered on each OrderCard. Tapping it triggers a Zustand store action that emits a Socket.io "kot.bumped" event to the backend and removes the card from the local order list with a slide-out animation. The POS service receives the bump event and updates the order item status to "READY". The OrderBoard re-renders without the bumped card.

Acceptance Criteria​

Scenario: Cook bumps a completed order
Given the grill station has 4 active orders and Order #1042 (Tandoori Chicken) is ready
When the cook taps the BumpButton on Order #1042
Then the order card slides out of the grid with a smooth animation (300ms)
And a "kot.bumped" event is emitted via Socket.io with the order ID and station
And the remaining 3 orders re-arrange to fill the gap
And the POS service updates the order status to "READY" for the bumped items

Scenario: Accidental bump can be undone within 5 seconds
Given the cook accidentally bumps Order #1043
When the order slides out, an "Undo" toast appears at the bottom of the screen for 5 seconds
Then if the cook taps "Undo" within 5 seconds, the order card reappears in its original position
And the "kot.bumped" event is reversed via a "kot.unbumped" event
And if 5 seconds pass without tapping "Undo", the bump is finalized

Scenario: All items bumped triggers order completion
Given an order has 3 items split across grill (2 items) and salad (1 item) stations
When the grill cook bumps the 2 grill items and the salad cook bumps the 1 salad item
Then the entire order status changes to "READY" in the POS service
And the server's F&B app shows a notification: "Order #1042 ready for Table 7"

US-022-004: KDS Audio Alerts for New Orders​

As a kitchen cook working with my back to the display, I want to hear an audio alert when a new order arrives, So that I do not miss incoming orders during busy preparation.

Priority: P1 | Points: 3 | Sprint: 7 | Status: Not Started

Implementation Status​

Not implemented. The AlertBanner provides visual notification only. No audio playback code exists. The Electron main process could play sounds via the shell.beep() API or the renderer could use the Web Audio API with custom sound files. No sound assets are included in the project.

Acceptance Criteria​

Scenario: Audio alert plays when a new order arrives
Given the KDS is running on the grill station with audio enabled
When a new KOT with grill items arrives via Socket.io
Then a short alert sound (chime, ~1 second) plays through the display's speakers
And the sound is distinct from the system default notification sound
And the volume is configurable via a settings menu (low, medium, high, mute)

Scenario: Escalation sound for aging orders
Given Order #1050 has been on the board for 9 minutes (yellow zone)
When the timer crosses the 10-minute threshold into red zone
Then a different, more urgent alert sound plays (double beep)
And the sound repeats every 60 seconds while the order remains in red zone
And the repeating alert stops when the order is bumped

Scenario: Audio muted during quiet hours
Given the kitchen operates during quiet hours (10 PM - 6 AM) with reduced staff
When the KDS settings have "Quiet Mode" enabled for 22:00-06:00
Then no audio alerts play during this window
And visual alerts (banner, color coding) continue to function normally

US-022-005: KDS Multi-Station Expeditor View​

As an expeditor, I want to see orders from multiple stations on a single split-screen display, So that I can coordinate plating when a table's dishes come from different stations.

Priority: P2 | Points: 5 | Sprint: 9 | Status: Not Started

Implementation Status​

Not implemented. The StationFilter only supports single-station selection. The OrderBoard renders a single grid. A split-screen layout (e.g., left half = grill, right half = salad) with independent scrolling and bump controls is needed. The expeditor view should also highlight "table-complete" status (all items for a table ready across all stations).

Acceptance Criteria​

Scenario: Expeditor views two stations side by side
Given the expeditor display is configured for multi-station mode
When the expeditor selects "Grill" for the left panel and "Salad" for the right panel
Then the screen splits vertically with grill orders on the left and salad orders on the right
And each panel has its own StationFilter header, order grid, and scroll
And new orders appear in the correct panel based on their station assignment

Scenario: Table-complete indicator when all stations are done
Given Table 3 has an order with 2 grill items and 1 salad item
And the grill station has bumped both grill items
When the salad station bumps the salad item
Then a "TABLE 3 COMPLETE" banner flashes across the expeditor view for 5 seconds
And the expeditor knows to coordinate plating and call the server for pickup

Scenario: Expeditor can bump from either panel
Given the expeditor sees an order card in the grill panel
When the expeditor taps the BumpButton on that card
Then the bump is processed the same as if the grill cook bumped it
And the card is removed from the grill panel
And the corresponding items on the salad panel (if any remain) are unaffected

US-022-006: KDS KOT Reprint & Order Recall​

As a kitchen manager, I want to reprint a KOT on the thermal printer and recall recently completed orders, So that I can handle re-fire requests and resolve disputes about what was ordered.

Priority: P1 | Points: 5 | Sprint: 8 | Status: Partial

Implementation Status​

The KDS has a PrintButton component on each OrderCard and the main process includes an ESC/POS formatter (escpos-formatter.ts) and printer service (printer.service.ts). The formatter generates ESC/POS byte sequences for KOT layout (header, table number, items, footer). However, the printer service connection to physical/network printers is not validated end-to-end. Order recall (viewing bumped orders) is not implemented -- once bumped, the order is removed from the Zustand store with no history retention.

Acceptance Criteria​

Scenario: Kitchen manager reprints a KOT for active order
Given Order #1055 is currently displayed on the KDS
When the manager taps the PrintButton on Order #1055
Then the ESC/POS formatter generates the KOT layout: header (restaurant name, KOT number), table number, items with quantities and modifiers, timestamp, and footer
And the printer service sends the formatted data to the configured thermal printer
And the KOT prints within 3 seconds
And a "Printed" confirmation toast appears on the KDS

Scenario: Manager recalls a recently bumped order
Given Order #1050 was bumped (completed) 8 minutes ago
When the manager opens the "Recall" drawer from the KDS toolbar
Then a list of orders bumped in the last 30 minutes is displayed
And the manager can view Order #1050 details (items, table, time, who bumped it)
And the manager can tap "Re-fire" to create a new KOT with the same items and a "RE-FIRE" label
And the re-fired order appears on the active board as a new order card with a "RE-FIRE" badge

Scenario: Printer offline handled gracefully
Given the configured thermal printer is powered off or disconnected
When the manager taps PrintButton on an order
Then the KDS displays an error: "Printer offline. Check connection to [printer name/IP]."
And the print request is queued locally
And when the printer comes back online, the queued print jobs are automatically sent

US-022-007: Kiosk Self-Service Check-In Flow​

As a hotel guest, I want to check myself in at a kiosk by scanning my ID and selecting my room, So that I can skip the front desk queue and get to my room faster.

Priority: P0 | Points: 13 | Sprint: 6 | Status: Partial

Implementation Status​

The kiosk Electron app has renderer components for the full check-in flow: ReservationLookup (search by confirmation number or guest name), GuestVerification (display reservation details for guest confirmation), IdScanner (trigger ID document scan), RoomSelection (show available rooms matching reservation type), KeyDispenser (trigger key card encoding), ConfirmationScreen (display room number and welcome message), LanguageSelector (en/hi toggle). Hardware mock layer provides simulated responses for ID scanner, key encoder, payment terminal, and receipt printer. However, all backend API calls use mock data -- the reservation lookup does not call the reservation service, room assignment does not call the front desk service, and key encoding does not trigger real hardware. The flow works as a UI prototype but is not connected end-to-end.

Acceptance Criteria​

Scenario: Guest completes self-service check-in
Given a guest with confirmation number "HMP20260305001" arrives and approaches the kiosk
When the guest selects English, enters the confirmation number on the touchscreen
Then the kiosk calls GET /api/v1/reservations?confirmationNumber=HMP20260305001
And displays: guest name, dates (Mar 5-7), room type (Deluxe), and asks the guest to scan their ID
And after ID scan matches the guest record, available Deluxe rooms are shown (Room 402, 405, 410)
And the guest taps Room 405, the key card encoder activates and dispenses a programmed key
And the ConfirmationScreen shows: "Welcome, Mr. Patel! Room 405, Floor 4. Checkout: March 7."
And the entire flow completes in under 3 minutes

Scenario: Reservation not found redirects to front desk
Given a guest enters confirmation number "INVALID123"
When the kiosk calls the reservation lookup API and receives no results
Then the screen displays: "We couldn't find your reservation. Please visit the front desk for assistance."
And a "Try Again" button allows the guest to re-enter the confirmation number
And after 2 failed attempts, the kiosk shows front desk directions with a map/arrow

Scenario: Hardware failure falls back gracefully
Given the key card encoder is offline (hardware mock returns error)
When the guest completes ID verification and room selection
Then the kiosk displays: "Key card system is temporarily unavailable. Please collect your key at the front desk. Your room (405) has been assigned."
And the room assignment is saved in the backend so front desk can issue the key without re-doing check-in
And the kiosk logs the hardware failure event for IT team review

US-022-008: Kiosk Room Service Ordering​

As a hotel guest at the kiosk, I want to browse the room service menu and place an order charged to my room, So that I can order food conveniently without calling the restaurant or front desk.

Priority: P1 | Points: 8 | Sprint: 8 | Status: Not Started

Implementation Status​

Not implemented. The kiosk components are focused on the check-in flow. No menu browser, cart, or room service ordering UI exists. The POS service has menu endpoints and the billing service supports room charge posting, but no kiosk integration has been built.

Acceptance Criteria​

Scenario: Guest browses room service menu and places an order
Given a guest taps "Room Service" on the kiosk home screen
When the kiosk prompts for room number and the guest enters "405"
Then the guest is verified against the checked-in guest record for Room 405
And the room service menu loads with categories (Breakfast, Lunch, Dinner, Beverages, Snacks)
And the guest adds items to cart: 1x Club Sandwich (INR 450), 1x Fresh Lime Soda (INR 150)
And the cart shows subtotal (INR 600), GST (INR 30), and total (INR 630)
And the guest taps "Charge to Room" and confirms
And the order is created via POST /api/v1/pos/orders and charged to Room 405 folio

Scenario: Menu shows dietary information and allergen tags
Given the guest is browsing the menu
When viewing a menu item (e.g., "Paneer Tikka")
Then the item card shows: name, description, price, photo, and dietary tags (Vegetarian, Contains Dairy)
And a filter option allows showing only Vegetarian, Vegan, or Gluten-Free items
And items currently unavailable (out of stock) are greyed out with "Currently Unavailable" label

Scenario: Order confirmation with estimated delivery time
Given the guest confirms the room service order
When the order is successfully placed
Then the kiosk displays: "Your order has been placed! Estimated delivery: 30-40 minutes to Room 405."
And a KOT is sent to the room service KDS station
And the guest can view the order summary before the screen returns to the home screen after 15 seconds

US-022-009: Kiosk Multilingual & Accessibility​

As a hotel guest who does not speak English, I want to use the kiosk in Hindi (or other supported languages), So that I can complete check-in and other tasks independently.

Priority: P1 | Points: 5 | Sprint: 7 | Status: Partial

Implementation Status​

The LanguageSelector component exists and the i18n directory is set up in the kiosk renderer. The component allows toggling between English and Hindi. However, translation files may be incomplete (not all screen strings are externalized to i18n keys). Accessibility mode (high contrast, larger fonts, screen reader compatibility) is not implemented. Touch target sizes have not been audited against the 48px minimum.

Acceptance Criteria​

Scenario: Guest switches language to Hindi at kiosk start
Given the kiosk displays the welcome screen in English by default
When the guest taps the "Hindi" option on the LanguageSelector
Then all UI text switches to Hindi immediately (headings, labels, instructions, buttons)
And the reservation lookup screen displays: "अपना कन्फर्मेशन नंबर दर्ज करें"
And the language selection persists throughout the entire check-in flow
And after the session ends (30 seconds of inactivity), the kiosk resets to English

Scenario: Accessibility mode with high contrast and large fonts
Given the kiosk welcome screen has an accessibility icon in the top-right corner
When the guest taps the accessibility icon and enables "High Contrast" mode
Then all backgrounds change to solid black with white/yellow text
And font sizes increase by 50% (base 16px becomes 24px)
And touch target minimum size is enforced at 64px (increased from 48px)
And the mode persists for the current session

Scenario: All screens have complete translations
Given the i18n translation files for English and Hindi
When a QA engineer navigates through every kiosk screen in Hindi
Then no English text appears on any screen (all strings are translated)
And date/time formats follow Hindi locale conventions (e.g., "५ मार्च २०२६")
And currency formatting uses the Indian format (e.g., "₹ ६३०")