Appearance
Menu Management
Overview
Menus are collections of categories and items that can be assigned to locations and channels. A business can have multiple menus for different purposes (lunch, dinner, catering, etc.).
Key Purpose: Organize and assign menu content to locations and channels.
Purpose
This page lets you create, edit, publish, and manage menus that define which categories and items are available at each location and ordering channel.
Key Concepts
- Menu: A named collection of display groups (containing categories and items) assigned to a location, with a status (Draft, Published, Archive) and channel visibility settings.
- Menu Status: Menus follow a lifecycle of Draft, Published, and Archive. New menus are automatically set to Published on creation.
- Channel Visibility: Each menu specifies which channels it is visible on (Online Ordering, Kiosk, etc.). Changing visibility is blocked if the menu is actively used by a kiosk device profile.
- Display Groups: Menus contain display groups that define which categories and items appear. Display groups are synced when a menu is created or updated.
- Menu Name Uniqueness: Menu names must be unique per location; attempting to create or rename a menu to a name already in use at the same location returns a 400 error.
Actions
Create Menu
Add a new menu with a name, location, channel visibility, and display groups. The menu is automatically set to Published status and its display groups are synced.
Edit Menu
Update a menu's name, visibility, or display groups. Changes dispatch a MenuUpdated event (for Uber Eats sync) and a ReloadMenu event for all ordering channels.
Duplicate Menu
Create a copy of an existing menu including all its display groups. Each display group is duplicated and linked to the new menu.
Publish / Draft / Archive Menu
Change a menu's status. Setting a menu to Draft or Archive is blocked if the menu is currently assigned to any kiosk device profile with active devices. Publishing makes the menu available on its configured channels.
Delete Menu
Remove a menu and all its associated display groups permanently.
Location
- Backoffice Route:
/menus - Backend Controller:
app/Http/Controllers/Api/MenuController.php - Vue Component:
src/views/menus/index.vue
Concepts
Menu
A named collection containing categories and their items.
Menu Assignment
Linking a menu to a location and/or channel.
Menu Availability
Time-based rules for when a menu is active.
Fields
Menu Name
| Property | Value |
|---|---|
| Field ID | name |
| Label | Menu Name |
| Type | Text |
| Required | Yes |
| Validation | max: 100 characters |
Description: Name of the menu for internal reference and display.
Examples:
- "Main Menu"
- "Lunch Menu"
- "Dinner Menu"
- "Weekend Brunch"
- "Catering Menu"
- "Kids Menu"
Menu Description
| Property | Value |
|---|---|
| Field ID | description |
| Label | Description |
| Type | Textarea |
| Required | No |
| Validation | max: 300 characters |
Description: Optional description of the menu.
Examples:
- "Our full menu available all day"
- "Special lunch offerings, available 11am-3pm"
Categories
| Property | Value |
|---|---|
| Field ID | category_ids |
| Label | Categories |
| Type | Multi-select (sortable) |
| Required | Yes |
Description: Categories included in this menu, in display order.
Business Logic:
- Categories can be in multiple menus
- Order determines display sequence
- Items inherit from categories
Assigned Locations
| Property | Value |
|---|---|
| Field ID | location_ids |
| Label | Locations |
| Type | Multi-select |
| Required | No |
| Default | All locations |
Description: Which locations use this menu.
Business Logic:
- Empty = available at all locations
- Specific locations = only those locations
Default Menu
| Property | Value |
|---|---|
| Field ID | is_default |
| Label | Default Menu |
| Type | Toggle |
| Default | false |
Description: Whether this is the default menu for assigned locations.
Business Logic:
- Default menu shown when no schedule matches
- Only one default per location
Menu Active
| Property | Value |
|---|---|
| Field ID | active |
| Label | Active |
| Type | Toggle |
| Default | true |
Description: Whether this menu is currently active.
Menu Availability
Availability Type
| Property | Value |
|---|---|
| Field ID | availability_type |
| Label | Availability |
| Type | Select |
| Options | always, scheduled |
| Default | always |
Description: When this menu is available.
Options:
- Always: Menu available during all business hours
- Scheduled: Menu available during specific times
Schedule
| Property | Value |
|---|---|
| Field ID | schedule |
| Label | Schedule |
| Type | Weekly Schedule |
| Required | Yes (if scheduled) |
| Depends On | availability_type = scheduled |
Description: Days and times when this menu is available.
Structure:
json
{
"Monday": { "enabled": true, "from": "11:00", "to": "15:00" },
"Tuesday": { "enabled": true, "from": "11:00", "to": "15:00" },
...
}Valid From
| Property | Value |
|---|---|
| Field ID | valid_from |
| Label | Start Date |
| Type | Date |
| Required | No |
Description: Date when menu becomes available.
Use Cases:
- Seasonal menus
- Promotional menus
- New menu launches
Valid Until
| Property | Value |
|---|---|
| Field ID | valid_until |
| Label | End Date |
| Type | Date |
| Required | No |
Description: Date when menu expires.
Channel-Specific Menus
Online Ordering Menu
| Property | Value |
|---|---|
| Field ID | online_ordering_menu_id |
| Label | Online Ordering Menu |
| Type | Select |
| Scope | Location setting |
Description: Menu used for online ordering at this location.
Kiosk Menu
| Property | Value |
|---|---|
| Field ID | kiosk_menu_id |
| Label | Kiosk Menu |
| Type | Select |
| Scope | Device setting |
Description: Menu displayed on specific kiosk.
In-House Menu
| Property | Value |
|---|---|
| Field ID | in_house_menu_id |
| Label | In-House Menu |
| Type | Select |
| Scope | Location setting |
Description: Menu for dine-in/QR ordering.
Business Logic
Menu Selection
Customer opens ordering channel
│
▼
Get location's menus
│
▼
Filter by channel (online, kiosk, in-house)
│
▼
Filter by current date (valid_from/valid_until)
│
▼
Filter by current time (schedule)
│
▼
Multiple menus match?
├── Yes → Use priority/default
└── No match → Use default menu
│
▼
Display selected menuMenu Priority
When multiple menus could apply:
- Scheduled menu matching current time
- Default menu for location
- First active menu
Category Inheritance
Menu contains Categories
│
▼
Categories contain Items
│
▼
Items have Modifiers
│
▼
Full menu structure displayedCustomer Impact
Online Ordering
- Menu determines available items
- Scheduled menus change automatically
- Categories shown in menu order
Kiosk
- Assigned menu displayed
- Can differ from online menu
- Updates when menu changes
Menu Switching
- Automatic based on time
- Customer sees appropriate menu
- No manual intervention needed
Relations
Depends On
- Categories: Menus contain categories
- Locations: Menus assigned to locations
Affects
- Online Ordering: Which items available
- Kiosk: Which items displayed
- Reports: Sales by menu
Related Features
Business Rules
- Menu names must be unique per location; creating or renaming a menu to a name already used at the same location is rejected with a 400 error.
- New menus are automatically set to "Published" status on creation; there is no draft-first workflow unless the merchant explicitly changes the status afterward.
- A menu cannot be set to Draft or Archive if it is currently assigned to a kiosk device profile that has active devices; the system returns a 400 error to prevent breaking live kiosks.
- When a menu is deleted, all display groups associated with that menu are also deleted automatically.
- Updating a menu dispatches both a
MenuUpdatedevent (for Uber Eats integration sync) and aReloadMenuevent so all ordering channels reflect the change immediately.
FAQs
- Can I have different menus for online ordering and kiosk? Yes. Each location can assign different menus to different channels (online ordering, kiosk, in-house) through device profiles and location settings.
- What happens when I duplicate a menu? A new menu is created with all display groups copied. Each display group is duplicated independently and linked to the new menu, so changes to the copy do not affect the original.
- Can a menu be assigned to multiple locations? Menus are created per location. To use the same menu structure at another location, duplicate it and assign it there.
- What is the difference between Draft and Archive? Both statuses hide the menu from customers, but Draft indicates work-in-progress while Archive indicates a menu that is no longer needed. Neither can be set if the menu is actively used by kiosk devices.
- Does publishing a menu make it immediately visible to customers? Yes, publishing sets the menu status to "Published" and it becomes available on all configured channels for the assigned location right away.
Troubleshooting
Problem: Menu not showing
Causes:
- Menu not active
- Menu not assigned to location
- Outside schedule/date range
- No categories in menu
Solutions:
- Activate menu
- Assign to location
- Check schedule settings
- Add categories
Problem: Wrong menu displaying
Causes:
- Schedule overlap
- Wrong default menu
- Time zone issue
Solutions:
- Review menu schedules
- Set correct default
- Check location timezone
Problem: Items missing from menu
Causes:
- Category not in menu
- Item not in category
- Item unavailable
Solutions:
- Add category to menu
- Assign item to category
- Enable item availability
Problem: Menu not switching at scheduled time
Causes:
- Schedule not configured correctly
- Cache not refreshed
- Timezone mismatch
Solutions:
- Review schedule settings
- Clear cache
- Verify timezone
Examples
Single Menu (Simple)
json
{
"name": "Main Menu",
"description": "Our full menu",
"category_ids": ["starters", "mains", "desserts", "drinks"],
"location_ids": [],
"is_default": true,
"active": true,
"availability_type": "always"
}Lunch & Dinner Menus
json
{
"menus": [
{
"name": "Lunch Menu",
"category_ids": ["lunch-specials", "sandwiches", "salads", "drinks"],
"is_default": false,
"availability_type": "scheduled",
"schedule": {
"Monday": { "enabled": true, "from": "11:00", "to": "15:00" },
"Tuesday": { "enabled": true, "from": "11:00", "to": "15:00" },
"Wednesday": { "enabled": true, "from": "11:00", "to": "15:00" },
"Thursday": { "enabled": true, "from": "11:00", "to": "15:00" },
"Friday": { "enabled": true, "from": "11:00", "to": "15:00" },
"Saturday": { "enabled": false },
"Sunday": { "enabled": false }
}
},
{
"name": "Dinner Menu",
"category_ids": ["starters", "mains", "steaks", "desserts", "wines", "drinks"],
"is_default": true,
"availability_type": "scheduled",
"schedule": {
"Monday": { "enabled": true, "from": "17:00", "to": "22:00" },
"Tuesday": { "enabled": true, "from": "17:00", "to": "22:00" },
"Wednesday": { "enabled": true, "from": "17:00", "to": "22:00" },
"Thursday": { "enabled": true, "from": "17:00", "to": "22:00" },
"Friday": { "enabled": true, "from": "17:00", "to": "23:00" },
"Saturday": { "enabled": true, "from": "17:00", "to": "23:00" },
"Sunday": { "enabled": true, "from": "17:00", "to": "21:00" }
}
}
]
}Weekend Brunch Menu
json
{
"name": "Weekend Brunch",
"category_ids": ["brunch-mains", "eggs", "pancakes", "brunch-drinks"],
"is_default": false,
"availability_type": "scheduled",
"schedule": {
"Monday": { "enabled": false },
"Tuesday": { "enabled": false },
"Wednesday": { "enabled": false },
"Thursday": { "enabled": false },
"Friday": { "enabled": false },
"Saturday": { "enabled": true, "from": "09:00", "to": "14:00" },
"Sunday": { "enabled": true, "from": "09:00", "to": "14:00" }
}
}Seasonal Menu
json
{
"name": "Summer Specials",
"category_ids": ["summer-salads", "grilled-items", "frozen-drinks"],
"is_default": false,
"active": true,
"availability_type": "always",
"valid_from": "2024-06-01",
"valid_until": "2024-08-31"
}Different Menus per Channel
json
{
"location": {
"name": "Main Location",
"online_ordering_menu_id": "menu-online",
"in_house_menu_id": "menu-full"
},
"menus": [
{
"id": "menu-online",
"name": "Online Menu",
"description": "Streamlined menu for delivery",
"category_ids": ["popular", "mains", "sides", "drinks"]
},
{
"id": "menu-full",
"name": "Full Menu",
"description": "Complete dine-in menu",
"category_ids": ["starters", "salads", "mains", "specials", "desserts", "wines", "cocktails", "drinks"]
}
]
}