A local ramen restaurant was managing reservations manually — over the phone, through DMs, and on paper. This created friction for customers, scheduling headaches for staff, and no visibility into trends or capacity. I designed and built a full-stack booking web app to solve this end-to-end: a polished customer-facing booking flow, a multi-view staff dashboard, analytics, and a branding system that lets the restaurant customise the entire look and feel without touching code.
The app is live, deployed on Railway, and integrated directly into the restaurant's website.
My workflow for this project followed a disciplined, client-first process:
The customer experience was designed to be frictionless and low-anxiety — minimal steps, clear feedback, and no account required.
![Booking flow — calendar and time slot selection][PLACEHOLDER: Screenshot of the booking page showing the 7-day calendar and time slot picker]
What it does:
![Booking confirmation and manage reservation screen][PLACEHOLDER: Screenshot of the confirmation screen and the manage reservation page]
Managing reservations without an account:
Customers can access their reservation two ways — via a secure token link in their confirmation email, or by requesting a 4-digit OTP sent to their email. From there they can edit the date, time, duration, party size, or special requests, or cancel outright. Cancellations are locked within 1 hour of the booking time. Automated 24-hour and 2-hour reminder emails are sent via a background cron job.
The dashboard was built to be genuinely useful across a full restaurant workday — not just a data dump, but an operational tool.
![Staff dashboard — day view with reservation detail sidebar][PLACEHOLDER: Screenshot of the staff dashboard day view with reservation sidebar open]
Day, week, and month views:
![Staff dashboard — week and month views][PLACEHOLDER: Screenshot of the week and month views side by side]
Status and exports:
Staff can mark reservations as confirmed, completed, no-show, or cancelled directly from the dashboard. Admins can download a full .xlsx export of reservations with complete change history. Access is role-controlled across three tiers: Super Admin, Admin, and Staff.
Seven chart types give the restaurant real data on how it's performing — not just raw booking numbers.
![Analytics page — charts overview][PLACEHOLDER: Screenshot of the analytics page showing multiple chart types]
The analytics suite covers volume trends, capacity utilisation, no-show and cancellation rates, party size distribution, booking lead time, a peak time heatmap, and return customer rate. All charts are powered by Recharts and scoped to configurable date ranges.
One of the more technically interesting parts of the project was building a fully dynamic branding system. All cosmetic settings are stored in the database and applied at runtime — no rebuild required.
![Branding settings tab — colour picker and font selector][PLACEHOLDER: Screenshot of the Settings → Branding tab]
A public API endpoint returns the current brand config; a useBranding hook on the client fetches these settings and applies them as CSS custom properties on document.documentElement. Colours are stored as hex and converted to HSL at runtime so Tailwind and Radix components can correctly derive hover and muted variants. The selected Google Font is injected dynamically. The favicon mirrors the uploaded logo automatically.
Configurable without touching code:
Logo (SVG, PNG, WebP, JPEG), tagline, address, display font (8 Google Font options), primary colour, header text colour, page background colour, and accent colour.
The default theme for Ono Ramen uses a deep crimson (#7B2528), warm cream (#F7F4EF), warm gold accent (#CFA131), and Bebas Neue as the display font.
A 9-tab settings panel covers every configurable aspect of the system.
![Settings panel — tabs overview][PLACEHOLDER: Screenshot of the settings panel showing multiple tabs]
| Tab | What it controls |
|---|---|
| General | Restaurant name, contact info, SMTP email config |
| Branding | Logo, colours, font, tagline, address |
| Hours & Blackout | Operating hours per day, blackout dates with conflict alerting |
| Booking Rules | Party size limits, slot duration options, advance booking window |
| Email Templates | Fully customisable transactional email HTML via TipTap rich text editor |
| Staff | Create, edit, and delete staff accounts; role assignment |
| Integrations | Google Calendar OAuth connection; iCal feed URL |
| Audit Log | Paginated log of all staff actions |
| Danger Zone | Rate limit toggle, reservation purge (Super Admin only) |
Google Calendar integration syncs reservations as calendar events automatically. Edits and cancellations update or delete the corresponding event. A background sync job runs every 30 minutes to catch any missed events. OAuth tokens are encrypted at rest. An iCal feed is also available for any third-party calendar app.
React 18 · TypeScript · Vite · React Router · TanStack Query · React Hook Form + Zod · Radix UI · Tailwind CSS · Recharts · TipTap · date-fns · Cloudflare Turnstile
Express · TypeScript · Prisma ORM · PostgreSQL · JWT + bcrypt · Helmet · CORS · Rate limiting · Nodemailer (SMTP) + Resend (fallback) · Google Calendar API · ExcelJS · Zod
Railway (Nixpacks build) · Railway PostgreSQL · Single Node.js process serving API + SPA · prisma migrate deploy on every deploy
Several security measures were built in from the start rather than added on:
The app went from PRD to live deployment, fully integrated into the client's website. Staff moved off manual tracking entirely. The client gained real visibility into their reservation patterns, peak times, and no-show rates for the first time. The booking flow handles both the customer-facing experience and all staff operations from a single deployed service.
Ono Ramen is part of Kulon Pte. Ltd., a Singapore-based F&B brand. Kulon Bakmi, its sister brand, has been featured in Time Out Singapore's "Recommends" list from 2020 to 2023.