Masadan Sipariş
A self-hosted QR ordering system built for a real restaurant, from the customer’s phone to the kitchen printer.
- Role
- Solo developer — design, build, and deployment
- Year
- 2026
- Stack
- TypeScript, Next.js 16 (App Router), React 19, Tailwind CSS 4, PostgreSQL, Prisma 6, Server-Sent Events, Zod, jose, bcryptjs, sharp, ESC/POS over TCP, Vitest, GitHub Actions
- Links
Problem
A restaurant (Heaven Restaurant, ~25–30 tables) needed guests to order from their own phones without installing an app or creating an account — and the orders had to reach the kitchen reliably, on existing hardware, without depending on a third-party cloud service.
What I did
I built a single self-hosted Next.js application that runs on the venue’s own network. Guests scan a signed table QR code, browse a bilingual (Turkish/English) menu, order, and follow status live over Server-Sent Events; staff manage tickets and table bills from a live desk.
The security model was a real design problem: QR codes carry an HMAC signature, table sessions expire and are capped per table, and an order-attempt ledger records abuse.
The hardest part was hardware. Accepted orders go into a PostgreSQL “outbox” that an on-premises bridge agent pulls and prints over TCP to an ESC/POS kitchen printer, with claims, acknowledgements, retries, and failed-delivery handling so a printer problem never silently loses a ticket.
Outcome
A complete end-to-end system — scan → order → staff acceptance → kitchen print — designed to run as a supervised service on one machine, with CI (lint, type-checks, Vitest) covering QR/session validation, auth, rate limits, order idempotency, billing, and the printer protocol.
It deliberately avoids Redis, hosted storage, and external schedulers so a small venue can actually run and maintain it.