08 · In production
Caramelקרמל
A menu site and CMS for a gluten-free café in Akko.
Caramel is a gluten-free café on the fishermen’s square in Akko. Its public menu, in Hebrew and right to left, shows every dish with its price and availability, whether the café is open now, its weekly hours and the way there; the same content is edited from a protected admin portal. Built with Lama, live at caramel.darb.co.il, and Darb REST’s first client.
- Nour’s role
- Built with Lama · Menu site, CMS, PWA and performance
- Status
- Live at caramel.darb.co.il. Menu, prices, hours and photos are managed from its admin portal.

What is real today
Live
- The public Hebrew menu at caramel.darb.co.il: categories, dishes and prices, open status, weekly hours and directions
- The admin portal for the profile, hero media, categories, dishes, hours, social links and SEO
- Caramel is Darb REST’s first client, served on a Darb address
Not claimed
- caramel.darb.co.il is a menu: it takes no orders and no payments
- The ordering counter on this page is built in this portfolio on top of Caramel’s live menu. It prepares a WhatsApp message and stores nothing, and it is in test mode: visitors cannot send an order yet
- The repository has no automated test suite; its checks are lint, typecheck and build
The problem
Guests of a gluten-free kitchen check before they come: what is on the menu, what it costs, whether a dish is available today and whether the place is open. A photographed printed menu stops being true the day a price or an opening hour changes.
The café has to make those changes itself, the same day, without a developer and without a rebuild of the site.
How it works
01
Content lives in the database, not in the code: the restaurant profile, hero media, categories, dishes, opening hours, social links and SEO copy are Supabase rows and storage objects, and the public page reads them at request time, so an edit shows up without a deploy.
02
One admin portal edits that same content: signed-in administrators manage order, visibility, availability, prices, photos, overnight opening intervals and SEO fields through authenticated server actions. The browser only ever holds the publishable key.
03
Access is enforced in Postgres: row-level security on every application table and on storage, writes only for private.is_admin(), and public reads only while the restaurant profile is active. An inactive profile shows no catalog and is not indexed.
Try it
Caramel’s real menu, read live from its database: the prices, sold-out dishes and opening hours are the café’s own, as they are right now. Add dishes to a tray and go through pickup and payment. The ordering is built in this portfolio and is in test mode, so no order is sent.
Selected capabilities
Hebrew, right to left
An RTL layout with a skip link, a keyboard-operable category rail, native dialogs with labelled titles, visible focus rings and reduced motion respected.
Open or closed, computed
The open state is derived from the weekly hours in the Asia/Jerusalem time zone, including intervals that run past midnight.
A menu made for phones
Category navigation reflected in the URL, horizontal dish rails and a dish dialog with name, price, description and photo. Unavailable dishes stay visible, marked as such.
Installable
A web manifest, app icons and a production service worker. Offline, the page shows a reconnect screen; menu data, prices and admin pages are never cached.
Search and sharing
Metadata from the profile and SEO settings, an Open Graph image, sitemap, robots and Restaurant JSON-LD with hours and social links.
Guarded media
Public storage buckets for dishes, categories, hero media and branding, with MIME and size limits, admin-only writes and upload checks in the browser before anything is stored.
Architecture
One Next.js application with separate route groups for the public site, the CMS and authentication, over a hosted Supabase project.
app/(public)
The public menu: Server Components read through services/; client islands for the category rail, dish dialogs and media.
app/admin
The CMS: authorization checked in the protected layout, writes as server actions (features/*/actions.ts) that revalidate the public page.
Supabase
Postgres with RLS on every table and storage bucket; admin membership lives in a private schema that the Data API does not expose.
Deployment
The Next.js app on Vercel and a hosted Supabase project, served at caramel.darb.co.il.
- Next.js 16
- React 19
- TypeScript (strict)
- Tailwind CSS 4
- Supabase · Postgres · RLS · Storage
- Motion
- PWA · service worker
The live product
Captures of the public production site, caramel.darb.co.il. The logo and the footer are left out of frame: both show the café’s phone number.



