← ALL WORK
Web application2025

Menula

Menula is a multi-tenant QR menu platform. Each restaurant gets a live menu at menula.app/<slug>, rendered by one React 19 + TypeScript single-page app that pulls the venue's categories, items, prices, banners, languages, and brand colors from a Go REST API at runtime. A template factory picks the layout per venue — stock styles for self-serve customers, plus bespoke slug-pinned designs built for individual clients. Menus are trilingual (English, Arabic, Kurdish) with full RTL mirroring and shareable /<slug>/<lang> deep links. Five client restaurants run on it in production today — Ocakbaşı Mustafa, Monaco, Liqaa Coffee, Your Fries, and Milla Baklava — and owners update content instantly without any redeploy.

Project Overview

Restaurants need menus that change daily — prices, availability, new items — but reprinting paper menus or rebuilding a static site for every change doesn't scale. Menula solves this with one frontend that serves every venue: scan a QR code, land on menula.app/<slug>, and the app fetches that restaurant's full menu from the API and renders it in the venue's own template and brand colors. Delivered: a marketing landing page with pricing, a dynamic restaurant loader with subscription-expired and not-found states, eleven registered menu templates including five bespoke client designs now live in production, and a public demo. The same codebase serves a kebab house, a coffee shop, and a baklava brand — each looking nothing alike.

Features & Functionality

Diners get a mobile-first menu with a sticky category rail, item cards with photos and prices, banner carousels, and item detail views. A language drawer switches between English, Arabic, and Kurdish; the layout mirrors to RTL per language, and /<slug>/<lang> URLs deep-link straight into a chosen language. Items carry availability flags and support single prices or ranges. Menu edits made by the owner appear on the next scan — data is fetched live, so nothing is baked into the build. Expired subscriptions return a dedicated state instead of a broken page. The landing page presents the six self-serve styles, feature grid, $10/month and $100/year pricing, and the companion iOS management app.

Development & Technology

The frontend is React 19 with strict TypeScript, built on Vite 7 and styled with Tailwind CSS 4. React Router 7 handles three routes: the landing page, /:slug, and /:slug/:lang. Axios fetches from the Go backend at server.menula.app, mapping HTTP 402 to a subscription-expired state and 404 to not-found; TanStack Query caches responses per slug. An adapter layer normalizes the API's multi-language string arrays into a clean UI model, and a TemplateFactory switch maps each venue's theme — or a slug-pinned override for bespoke clients — to one of eleven layout components. A resolver aliases URL segments like /ar to the backend's display-label language codes. GSAP, Embla, and Swiper drive animation and carousels; dialogs and drawers use Radix UI and Vaul.

Performance, SEO & Deployment

The app ships as a static Vite production build (tsc -b && vite build) served at menula.app, with all menu content loaded at runtime — so client updates go live instantly with zero redeploys. An inline script in index.html paints each bespoke venue's background color before the React bundle even loads, killing the white flash on QR scans, and a status-bar hook keeps the mobile browser chrome synced to each venue's backend-driven palette via the theme-color meta tag and CSS variables. Fonts and per-venue image assets are self-hosted from the public folder. React Query's per-slug cache avoids refetching on navigation. The viewport uses viewport-fit=cover with safe-area insets so menus render edge-to-edge on modern phones.

( GALLERY )

Menula — image 1
Menula — image 2
Menula — image 3
Menula — image 4
Menula — image 5
Menula — image 6
Menula — image 7