A self-serve kiosk ordering system for pop-up kitchens, garden kitchens, and small food venues. Customers scan a QR code on their phone, build their order, and track it in real time. The kitchen sees a live order queue and can print tickets to a Bluetooth receipt printer.
ByteOrder runs in two modes:
| Mode | Who it's for |
|---|---|
| Self-hosted | Single kitchen, simple env-var login, no external auth service required |
| Cloud | Multi-tenant SaaS — each kitchen is isolated by Clerk organisation |
- Display the kiosk screen (
/) — it shows a QR code and the live order queue - Customers scan the QR code, enter their name, pick items, and place the order
- The kitchen admin panel shows a live queue — advance orders through Pending → In Progress → Ready → Completed
- When an order is placed the print service fires a ticket to your receipt printer
- Customers track their order status in real time on their phone
| Service | Stack | Purpose |
|---|---|---|
frontend |
React + Vite + Tailwind | Mobile-first customer ordering UI, QR code home screen |
admin |
React + Vite + Tailwind + Express | Menu management, order queue, settings, auth |
menu-service |
Python / FastAPI | CRUD for categories, items, ingredients, option groups, settings |
order-service |
Python / FastAPI + SSE | Order lifecycle, queue position, real-time status streaming |
print-service |
Python worker | Subscribes to Redis, POSTs formatted tickets to an HTTP printer endpoint |
postgres |
PostgreSQL 16 | Persistent store |
redis |
Redis 7 | Pub/sub for real-time SSE updates |
- Docker with Compose v2
AUTH_MODE=self-hosted
POSTGRES_PASSWORD=changeme
ADMIN_USERNAME=admin
ADMIN_PASSWORD=changeme # change this
JWT_SECRET= # generate: openssl rand -base64 32cd deploy
docker compose up -d| URL | What |
|---|---|
http://localhost:3000 |
Customer ordering frontend |
http://localhost:3001 |
Kitchen admin panel |
Sign in at the admin panel with the ADMIN_USERNAME / ADMIN_PASSWORD you set above.
In self-hosted mode the customer ordering page is served directly at /order:
http://your-server/order
Set the Frontend URL in Admin → Settings to your public address so the QR code on the kiosk screen is correct.
helm install byteorder deploy/helm/byteorder \
-n byteorder --create-namespace \
-f your-values.yamlMinimal values.yaml for self-hosted:
authMode: self-hosted
selfHosted:
adminUsername: admin
adminPassword: "your-strong-password" # required
jwtSecret: "your-long-random-string" # required
defaultKitchenId: default
defaultKitchenSlug: my-kitchen # optional — sets the /k/<slug> alias
postgres:
enabled: true
password: changeme
ingress:
enabled: true
frontendHost: order.example.com
adminHost: admin.example.com
tls:
enabled: true
clusterIssuer: letsencrypt-prodRequires a Clerk application with organisation support enabled.
authMode: cloud
clerk:
publishableKey: "pk_live_..."
secretKey: "sk_live_..."
postgres:
enabled: false
existingSecret: my-db-secret
existingSecretKey: uri
ingress:
enabled: true
frontendHost: order.example.com
adminHost: admin.example.com
tls:
enabled: true
clusterIssuer: letsencrypt-prodEach Clerk organisation maps to one kitchen. The admin sets a friendly slug in Admin → Settings; the customer URL is then order.example.com/k/<slug>/order.
- Admin → Menu Management — create Categories (e.g. Burgers, Sides) and Items within them
- Admin → Ingredients — create toppings and modifiers
- Attach ingredients to items in Menu Management:
- First click — optional topping (starts unselected)
- Second click — pre-selected by default
- Third click — removes from item
- Use Option Groups (▼ on each item) for mutually exclusive choices like Size
Admin → Settings lets you customise:
- Kitchen name and slug
- Brand colours (primary, background, surface, text)
- Logo (uploaded as base64)
- Frontend URL (used to generate the QR code)
- Printer URL (for the HTTP print-service)
ByteOrder supports two printer backends:
A Raspberry Pi Zero W acts as a dedicated print client. It auto-registers with the backend and pairs to a Bluetooth receipt printer via BLE.
Setup:
- Flash Raspberry Pi OS Bookworm Lite to a micro-SD card
- Copy the
pi-printer-client/directory to the Pi and run the installer:sudo bash install.sh
- On first boot the Pi broadcasts a
ByteOrder-XXXXXXWiFi network - Connect your phone to it — a setup page opens automatically (captive portal)
- Enter your WiFi credentials and the ByteOrder API base URL
- Note the claim code shown on the setup page (6 hex characters)
- In Admin → Printers, enter the claim code and a name for the printer
- The printer is now live — orders will print automatically
Run ble-printer-server on any machine next to the printer:
docker run -d --privileged --net=host \
ghcr.io/proffalken/ble-print-server:latestThen set the printer URL in Admin → Settings → Printer URL to http://<machine-ip>:8080.
The kiosk home screen (/) shows a QR code that links customers to /order (self-hosted) or /k/<slug>/order (cloud). Set Frontend URL in Admin → Settings to your public-facing address.
ByteOrder is instrumented with OpenTelemetry. For Dash0:
helm upgrade byteorder deploy/helm/byteorder \
-n byteorder --reuse-values --set dash0.enabled=trueFor docker-compose, set OTEL_ENDPOINT in your .env:
OTEL_ENDPOINT=http://your-otel-collector:4317| Variable | Services | Description |
|---|---|---|
AUTH_MODE |
all | cloud (default) or self-hosted |
DATABASE_URL |
menu, order, print, admin | Full PostgreSQL DSN |
REDIS_URL |
order, print | Redis URL (default redis://redis:6379) |
ADMIN_USERNAME |
admin | Login username (self-hosted only) |
ADMIN_PASSWORD |
admin | Login password (self-hosted only) |
JWT_SECRET |
admin | JWT signing secret (self-hosted only) |
DEFAULT_KITCHEN_ID |
menu, order, admin | Kitchen ID in self-hosted mode (default "default") |
DEFAULT_KITCHEN_SLUG |
menu | Slug seeded into kitchens table on first start (self-hosted only) |
CLERK_PUBLISHABLE_KEY |
admin | Clerk publishable key (cloud only) |
CLERK_SECRET_KEY |
admin | Clerk secret key (cloud only) |
MENU_SERVICE_URL |
admin | Internal URL of menu-service |
ORDER_SERVICE_URL |
admin | Internal URL of order-service |
OTEL_ENDPOINT |
all | OpenTelemetry collector endpoint (optional) |
cd deploy
docker compose buildMulti-arch builds (linux/amd64 + linux/arm64) are handled by GitHub Actions on every push to main.
Pull requests are welcome. Please open an issue first to discuss significant changes.
Copyright © 2026 Matthew Wallace
Released under the GNU Affero General Public License v3.0.
You are free to use, modify, and self-host this software. If you offer it as a hosted or managed service, the AGPL requires you to make any modifications publicly available under the same licence.