Customer Menu
The customer menu is the public-facing web page at handy.cafe/{your-slug}. Customers access it by scanning the QR code on their table. This page describes the customer flow end to end so you can explain it to staff and plan your rollout.
URL Structure
Every table has a unique URL of the form handy.cafe/{cafe-slug}/{table-code}. The QR code encodes this URL plus a short-lived token that proves the sticker is authentic. When the customer scans the QR:
- Their phone opens the URL in the default browser.
- The page resolves the slug and table code against the cloud API.
- If the table is
out_of_order, the page shows an unavailable notice. - If the table is
idle, the page explains that staff has not yet seated the customer and asks them to call for assistance. - If the table is
in_use, the page prompts for the 6-digit security code.
Security Code Verification
The security code ensures that only the customer currently seated at the table can place orders. It prevents someone who saw the QR from a photo or from outside your cafe from placing fraudulent orders.
After the customer enters the code:
- The API validates the code against the hashed value stored on the table.
- If valid, a session is created and a token is returned.
- The token is stored in a cookie (
hc_menu_session). A Bearer token fallback is also persisted in the device's local storage. This is necessary on iPhone Safari, which may block third-party cookies in some configurations. - The customer is redirected to the menu.
The session is valid for 24 hours from issue. If the customer closes the browser and returns on the same device, the session still works and they can re-enter without re-verifying.
Languages
The menu supports 24 languages: Arabic, German, Greek, English, Spanish, Farsi, French, Hindi, Indonesian, Italian, Japanese, Korean, Malay, Polish, Portuguese, Romanian, Russian, Thai, Tagalog, Turkish, Ukrainian, Urdu, Vietnamese, and Chinese.
On first visit, the page inspects the Accept-Language header from the browser and picks the best match. The customer can override the language at any time using the picker at the top of the menu. The chosen language is remembered for the session.
Product names, descriptions, and ingredients are not auto-translated; they appear in whatever language you entered in the menu editor. UI labels such as "Add to Cart", "Checkout", and payment flow messages are fully localized.
Theme
The menu supports a light theme and a dark theme. The default is device-aware: if the customer's operating system is set to dark mode, the menu opens in dark mode. A theme toggle at the top lets the customer switch.
Branded Header
The header at the top of the menu displays:
| Element | Source |
|---|---|
| Header Image | Uploaded from Settings > Cafeteria (optional) |
| Logo | Uploaded from Settings > Cafeteria |
| Display Name | From your business profile |
| Address | From your business profile (shown in footer) |
| Phone | From your business profile (shown in footer) |
Customize these fields for the best customer impression. Customers recognize the brand when the menu looks like your venue's physical signage.
Menu Browsing
The menu is grouped by category. Within a category, products are shown with a thumbnail, name, short description, and price.
Tapping a product opens the product sheet. The sheet shows:
- The full photo.
- Markdown description.
- Ingredients line.
- Preparation time chip (only when Show Prep Time on Menu is enabled).
- Unit label if configured (for example "250 ml").
- Variant selectors for any variant groups attached to the product.
- Quantity stepper.
- An Add to Cart button.
Required variant groups block the Add to Cart button until the customer selects an option.
Cart
The cart icon sits in a persistent location so customers can reach it from any screen. Cart contents persist across navigation within the site; browsing from cart to menu and back does not lose items.
The cart lets the customer:
- Adjust quantity per line.
- Remove a line.
- Add an optional note.
- Provide a phone number (optional).
The subtotal, VAT, and total are shown in real time.
Placing the Order
The Checkout step offers one or two payment methods depending on your configuration:
Cash
If online payment is disabled in your settings, only Cash is shown. The customer confirms the order and it is submitted immediately. The customer pays the cashier when the order arrives.
Online (Stripe Checkout)
If online payment is enabled, Online appears as an option. On submit:
- The order is created in a pending state.
- A Stripe Checkout client secret is returned.
- The Stripe embedded UI opens inline. The customer enters card details.
- On successful authorization, Stripe confirms the charge and the order moves to paid.
- The customer sees the success page.
Failed or abandoned payments leave the order in pending state. A second attempt can be made from the same session, or staff can cancel the order from the Orders dashboard.
Success Page
After a successful submission, the customer lands on a receipt page that shows:
- Order number and time.
- Every line with quantity, variants, and line total.
- Subtotal, VAT, and grand total.
- Payment method.
- Payment status icon (pending for cash; paid for online).
- A "Place Another Order" CTA that returns to the menu with the session intact.
- A "Back to Menu" link.
Order Status Polling
After submission, the customer's view of the order polls the status endpoint to reflect updates from the kitchen. If your staff advances an item from preparing to ready, the customer sees the badge on the line update automatically within seconds.
This is useful for self-service pickup at a counter. The customer can relax at the table until the menu tells them the order is ready.
What Customers Cannot Do
- Customers cannot browse the menu without the security code. The verification step is always required.
- Customers cannot place orders for tables that are idle or out_of_order.
- Customers cannot edit or cancel an order after it has been submitted. Cancellation is a staff action from the Orders dashboard.
Tips for a Clean Customer Experience
- Print QR stickers with the cafe name and a clear instruction such as "Scan to order. Ask staff for the code." Customers sometimes miss the verification step otherwise.
- Keep category and product names short. Long names wrap on mobile and push images below the fold.
- Upload at least one photo per product. Image-heavy menus convert higher than text-only menus.
- Enable Show Prep Time on Menu only after your dynamic estimate has trained. For the first 30 days the static value may be too generous or too tight, and customers notice.
- Test the full flow yourself from a phone before opening to customers. Scan a real QR, enter the code, place a test order, and verify that the order appears on your dashboard.