A menu site for a single cafe in El Gouna, sharing its approach with Le Garage - the same menu sync, Docker setup and operational commands - with everything a two-venue chain needs taken back out.
- Client
- Boho Cafe, El Gouna
- My role
- Architect and sole developer
- Period
- 2026

Project Overview
The second restaurant in El Gouna, and the first one paid for the groundwork. The menu source is the same till system with the same absence of an API, the deployment is the same shape, and the rules that took a live site to discover - never delete on sync, treat an empty source as a failure, let a human override the machine - came across intact. What did not come across is the chain. One cafe means a single venue row, menu URLs without a venue prefix, and none of the branching that two locations force on every query. That is a deletion, not a configuration flag: a disabled multi-venue model still costs a join on every page and a segment in every URL, and it would have to be revisited anyway if a second venue ever opened.
The project in numbers
- From foundations to a live site
Two days
Not because the site is trivial, but because the expensive parts - parsing a till system with no API, a sync that cannot lose data, Docker, migrations, operations - were already solved and tested on a live restaurant next door.
- Venue model
A chain, with a venue on every row
toA singleton, and flat menu URLs
One cafe, so the multi-venue plumbing came out rather than being carried along switched off. Adding a second venue later is a real piece of work, and pretending otherwise with an unused foreign key costs something on every query and every URL in the meantime.
- Menu sync
Same rules, inherited
Never deletes, marks unavailable instead; an empty response from the source is a failure, not an empty menu; anything entered by hand outranks the sync.
- Allergens and nutrition
Carried over, disclaimer and all
Including the distinction that matters: nothing recorded means the page says nothing, rather than implying a dish is clear.
Challenges
- Reusing a system built for a chain without inheriting the complexity a single cafe has no use for.
- Mirroring a menu from the same API-less till system, with the same holiday behaviour that punishes a sync that deletes.
- Publishing allergen and dietary information for a menu where most of it has never been recorded.
- Building against a database while keeping the build itself independent of one.
Solutions
- Reduced the venue model to a singleton: no venue column on categories and items, globally unique slugs, and URLs without a venue prefix.
- Carried the sync rules over intact - additive only, unavailable rather than deleted, empty source treated as a failure, manual decisions outranking the machine.
- Kept the distinction between unrecorded and checked-and-clear for allergens, so an unexamined dish stays silent instead of looking safe.
- Made the Prisma client lazy behind a proxy, so the build does not require a database connection and a page that queries at build time cannot break it.
- Kept every operation in the container and behind make targets, so migrations and syncs run the same way in development and production.
Key Features
- Single-Venue Menu - Categories, dishes and flat URLs, without chain plumbing.
- Mirrored Menu - Synced on a schedule from the till system, additively.
- Allergens & Diet Badges - Shown where recorded, silent where not.
- Nutrition - Per-dish figures, marked as estimates.
- Own Photography - House images that outrank whatever the source supplies.
- Structured Data - Schema.org built from the database.
Project Info
Technologies
Frontend
Backend
Hosting & Deployment
DevOps & CI/CD
Monitoring & Analytics
Need something like this?
Tell me what you are building and where it is stuck. I will tell you plainly whether it is work I should be doing.