Ramlyon
A restaurant operating system: a QR menu that takes WhatsApp, web and delivery orders, plus POS, kitchen display, staff roles and analytics. Works offline.
Recommended- Client
- Ramlyon, my own product
- My role
- Founder and full-stack engineer
- Type
- Multi-tenant SaaS
- Timeline
- May 2026 – present
- Built with
- Next.js
- TypeScript
- PostgreSQL
- Prisma
- Coolify
- Cloudflare
- React
- Tailwind CSS
- Jotai
- next-intl
- shadcn/ui
- Nginx
- Telegram
- Git
- GitHub
- Vitest
Screens14 screens
Screen 1 of 14
The diner's menu, opened from a table's QR codePhone · 1 / 14
Select the centre screen to see it full size.
Overview
Ramlyon is my own product: an operating system for restaurants and cafés. A venue starts with a QR menu that takes orders on WhatsApp, and grows into full operations on the same account (point of sale, kitchen display, delivery dispatch, staff roles, customers and analytics) without re-entering a single item.
I designed, built and launched it in under four months as a multi-tenant SaaS, and I run it in production: product, architecture, front end, back end, database, billing, deployment and operations. It is Arabic-first, works in 14 different languages, and keeps working when the restaurant's internet doesn't.
What I delivered
- QR menu on the venue's own subdomain, installable as its own app
- Ordering by WhatsApp, web checkout and delivery, with live order tracking for the diner
- Full-screen POS with variants, add-ons, discounts and printed receipts
- Real-time kitchen display and order board with a new-order alert
- Delivery zones, fees, a dispatch board and a driver role
- Menu editor with drag-to-reorder, variants, add-ons and per-item discounts
- QR designer with logo, gradients and a scannability check, plus print-ready table sheets
- Staff access: 6 built-in roles and custom roles from 48 permissions
- Analytics: 6 pages and 40 metrics, on the venue's own calendar day
- Offline-first dashboard that syncs safely when the connection returns
- Subscription billing: two plans, a free trial, local wallets and InstaPay
- Activity log, Excel and JSON export, and a platform-owner console
How I built it
Many restaurants, one platform
Every venue runs on the same deployment, and its data is isolated at the database layer, not by a filter someone has to remember. Each one gets its own address (yourcafe.ramlyon.com), its logo, colours and QR design, and a menu in up to 14 languages. Arabic and right to left are the default, not a translation.
Money the browser can't change
- Every amount is an integer in minor units (piastres), never a float.
- The POS and the web checkout show a total at once, then the server recomputes it from scratch, and that is the number saved.
- Every order is a frozen snapshot of names, prices, options, tax and service, so a price changed tomorrow never rewrites last week's reports.
Live screens without polling
A write fires pg_notify. One LISTEN connection per app instance builds the event once and fans it out to that venue's open tabs over server-sent events. Database work grows with writes, not with open screens: ten devices on all day cost the same as one.
Delivery addresses never ride the broadcast. The stream only says "delivery changed", and each screen re-reads what its role allows, so a chef or a driver never receives an address that isn't theirs.
Keeps working when the internet doesn't
The dashboard is an installable app. Orders, menu edits, customers and tables are written to a durable queue on the device and replayed when the connection returns:
- Replays are idempotent, so a retry never records an order twice.
- Changes to an order are sent as intentions ("mark ready", "add this item") and merged per line, so a waiter and the kitchen editing at the same second both survive.
- If the server refuses something done offline, the app rolls it back and says so.
A QR scan that costs zero queries
A menu scan used to cost five database reads. The page is now cached at Cloudflare's edge indefinitely and purged by host the moment the venue changes anything, so an edit shows at once and a scan usually costs nothing.
That only worked once the page stopped depending on the clock: "open" or "closed" is computed on the diner's phone from the venue's hours and timezone. I checked that logic against the server's across 10,752 cases, including daylight-saving changes.
Built for real counters
- Many tills run Windows 7, so the floor is Chrome 109, its last browser.
- Receipts and kitchen tickets print through the browser instead of raw ESC/POS, because cheap thermal printers mangle Arabic and the browser shapes it correctly.
- The POS keeps selling offline and prints without a round trip to the server.
Access that matches a restaurant
48 permissions across 14 areas, with 6 built-in roles: owner, manager, cashier, chef, waiter and driver. A chef can mark an item out of stock without being able to change its price. Every action passes four server-side gates: signed in, role, plan and an account in good standing. A feature the plan lacks is shown blurred with an upgrade, and a feature the role lacks isn't shown at all.
Billing that never holds data hostage
Two plans, Menu and Operations, with a 14-day trial, paid by InstaPay, mobile wallets or the EasyKash gateway. An unpaid account goes read-only after a 14-day grace period and is never deleted. Venues can export everything to Excel (14 sheets) or JSON at any time, and retention follows a published policy written against Egypt's data-protection law.
Running it
Hetzner servers through Coolify, behind Cloudflare, with images compressed on upload and served from R2. A health endpoint checks the database, R2, Cloudflare, email and Telegram, and a platform-owner console runs tenants, plans, payments and maintenance. I run it in production myself.
By the numbers
| Built and launched | under 4 months, by one engineer |
| Codebase | ~92,000 lines of TypeScript, 41 database models |
| Languages | 14, Arabic first |
| Permissions | 48, across 14 areas, 6 built-in roles |
| Analytics | 6 pages, 40 metrics |
| Database reads per menu scan | 5 → 0 |
