YumKiosk YumKiosk Docs
Website Agent login Owner panel
Getting Started

Architecture overview

How the kiosk, agent, and cloud components fit together.

Architecture overview

At a high level, YumKiosk is three components that talk to each other in real time:

   [ Kiosk tablet ]        [ Agent browser ]        [ YumKiosk cloud ]
         |                         |                         |
         |   POST /sessions/start  |                         |
         |------------------------>|                         |
         |                         |   broadcast incoming    |
         |                         |<------------------------|
         |                         |   POST /accept          |
         |                         |------------------------>|
         |   video + order state   |                         |
         |<===== Agora / WS ======>|                         |
         |                         |   POST /orders          |
         |                         |------------------------>|
         |   session completed     |                         |
         |<------------------------|                         |

The three tiers

The kiosk tier runs on any Android or iPad tablet. It's a web app served from api.yumkiosk.com — no native install, no Play Store submission. The kiosk is identified by a device_id that's generated on first launch and burned into localStorage. Owners pair a new kiosk by entering a 6-digit code on the owner panel, and the tablet trades that code for a long-lived device token.

The agent tier runs at agent.yumkiosk.com. Agents log in with email and password, opt in to "available" status, and start receiving incoming session events over a WebSocket. When they accept a call, the dashboard opens a video feed to the kiosk, shows the live menu, and exposes an order-builder UI. When the order is complete, the agent clicks End session, and the kiosk swaps back to its attract screen.

The cloud tier is a Laravel 12 monolith with a few supporting services. It handles authentication, session routing, order persistence, billing, and real-time fan-out. The cloud is split across multiple subdomains but is really one codebase:

  • api.yumkiosk.com — public kiosk-facing endpoints (no auth, device_id identified)
  • agent.yumkiosk.com — agent dashboard + private API
  • owner.yumkiosk.com — Filament-based owner panel
  • admin.yumkiosk.com — SuperAdmin panel (impersonation, tenant management)
  • docs.yumkiosk.com — this site

Real-time stack

Real-time messaging goes through Laravel Reverb, which is a first-party WebSocket server that speaks the Pusher protocol. Agents subscribe to a private agent.{id} channel for direct-to-agent events, and to a presence owner.{id} channel that broadcasts kiosk status to the owner dashboard. Kiosks fall back to long-polling via GET /api/public/sessions/{id}/status when a WebSocket isn't available (captive portals, restrictive networks, older hardware).

Video stack

Live video uses Agora. When a session starts, both the kiosk and the accepting agent fetch a signed Agora token from /api/public/agora/token (for the kiosk) or /api/agora/token (for the agent), then join the same channel named after the session UUID. Tokens are short-lived and refreshed automatically if a session runs over an hour.

Payment stack

There are two distinct payment flows:

  1. Diner → Restaurant: when a kiosk order is placed, it runs through the restaurant's own Stripe Connect account. YumKiosk never touches the money.
  2. Restaurant → YumKiosk: owners pay YumKiosk a subscription plus hourly agent charges through Stripe Billing on a standard merchant of record setup.

This two-sided split means restaurants keep control of their own processor relationship, while YumKiosk bills them cleanly each month for platform usage.