The MEX
An order management platform for The MEX Restaurant in Ireland: Stripe embedded checkout, 37 menu items across 10 categories, role-gated staff tools — and a kitchen that knows the moment a customer pays.
- Status
- Live · themexcobh.shop
- Timeline
- Aug — Nov 2025
- Role
- Freelance full-stack — paid client
- Stack
- React · Node · Express · PostgreSQL · Drizzle · Stripe · WebSockets
Live · client build
themexcobh.shop
NEW
#1042
2 items · paid
#1043
1 item · paid
IN PREP
#1040
4 items
#1041
3 items
READY
#1038
handed off
Stage 01 — Storefront
The customer-facing menu: browse, build an order, check out — without ever leaving the page.
- 37 menu items across 10 categories with live availability
- Cart state held client-side until checkout
- Order status visible to the customer in real time
The customer-facing menu: browse, build an order, check out — without ever leaving the page.
- 37 menu items across 10 categories with live availability
- Cart state held client-side until checkout
- Order status visible to the customer in real time
A kitchen can't wait on polling.
This was a paid client with a live restaurant, not a demo. Orders were confirming on a polling delay, payment had to feel seamless, and three very different audiences — customers, staff, admin — needed the same platform without seeing each other's controls.
Polling meant the kitchen learned about paid orders seconds late — and staff felt every second
Checkout had to stay inside the storefront: a redirect is where food orders go to die
One API, three audiences — customer, staff, admin — with no accidental crossover
Client work rewards boring, reliable choices — made early and enforced everywhere.
Push, don't poll
WebSocket events fan out the instant an order changes state. Confirmations now land 60% faster, and the kitchen board is never stale.
Tradeoff — Connection lifecycle to manage — reconnects, dropped sockets, ordering.
Stripe embedded, not redirected
Checkout renders inside the storefront and payment truth arrives by webhook. The customer never leaves; the kitchen never acts on an unpaid order.
Tradeoff — A tighter Stripe integration surface to own and maintain.
RBAC at the API boundary
JWT plus role checks on every route. One API serves three audiences, and the type system plus middleware make crossover impossible rather than unlikely.
Tradeoff — More middleware up front — fewer surprises forever.
Customer-facing menu, cart and live order tracking.
Menu
37 items · 10 categories
Cart + checkout
Stripe embedded in-page
Order tracking
live over WebSocket
0%
Faster confirmation
WebSocket push vs the old polling flow
0
Menu items live
across 10 categories · Stripe checkout
0 fps
Scroll performance
steady 60fps on the live build (measured)
0
Audiences, one API
customer · staff · admin via JWT + RBAC

- 19:42:03order.created — #1042 · 2 items
- 19:42:05payment.succeeded — stripe webhook
- 19:42:05ws.push → kitchen · order confirmed
- 19:42:05ws.push → customer · status: confirmed
- 19:48:11order.status — #1042 · in prep
- 19:57:40order.status — #1042 · ready
NEW
#1042
2 items · paid
#1043
1 item · paid
IN PREP
#1040
4 items
#1041
3 items
READY
#1038
handed off
#1039
awaiting pickup
- REQPOST /api/orders · role: customer → 201
- REQGET /api/kitchen/board · role: staff → 200
- REQGET /api/kitchen/board · role: customer → 403
- REQPATCH /api/menu/14 · role: admin → 200
- REQPATCH /api/menu/14 · role: staff → 403
- JWTevery route verifies before logic runs
Real-time is a product feature, not plumbing
Cutting confirmation delay by 60% didn't just make a number better — it changed how staff worked a dinner rush. The WebSocket layer was the most user-visible thing in the system.
Client work compresses you
A paying client with a live restaurant turns every decision honest: scope it, build it, ship it, stand behind it. The deadline pressure produced cleaner architecture, not messier.
Boring tools, calm production
Postgres, Express, JWT, Stripe — nothing exotic anywhere in the stack. Chosen precisely so production stays quiet while the restaurant is loud.