Skip to content

Menu Categories

Overview

Categories organize menu items into logical groups. They determine how items are displayed and navigated in Online Ordering and Kiosk.

Key Purpose: Organize menu items for easy customer navigation.

Purpose

This page lets you create, edit, and organize menu categories that group items into sections customers browse on online ordering and kiosk channels.

Key Concepts

  • Category: A named grouping of menu items with an optional description, an optional parent category, and an optional image. Items reference a category through their own category_id.
  • Parent Category: A category can optionally be nested under a parent category via parent_id, giving one level of nesting (subcategories). Only root (top-level) categories can be chosen as parents.
  • Multi-language Details: Category name and description are stored in a details map keyed by language, with default as the primary language entry.

Actions

Create Category

Add a new category with a name, optional description, optional parent category, and an optional image. The category is saved and synced to all active third-party integrations (Square, MplusKassa, etc.).

Edit Category

Update a category's name, description, parent category, or image. After saving, the cache for every item in the category is cleared so changes are reflected immediately, and the change is synced to active integrations.

Delete Category

Remove a category permanently. Deletion is blocked if the category still contains items -- all items must be reassigned or removed first.

Location

  • Backoffice Route: /menus/categories
  • Backend Controller: app/Http/Controllers/Api/BackOffice/CategoryController.php
  • Page: src/pages/menus/categories/index.vueView: src/views/reporting-categories/ReportingCategories.vue
  • Form: src/components/forms/items/CategoryForm.vue

Fields

Category Name

PropertyValue
Field IDdetails.name
LabelCategory Name
TypeText
RequiredYes
ValidationRequired string (no max length enforced)

Description: Name of the category shown to customers as a menu section header or navigation tab.

Best Practices:

  • Keep names short (1-3 words)
  • Use familiar terms customers expect
  • Be consistent with industry standards

Customer Impact:

  • Online Ordering: Tab/section header in menu
  • Kiosk: Large category buttons

Examples:

  • "Starters"
  • "Main Courses"
  • "Pizzas"
  • "Burgers"
  • "Drinks"
  • "Desserts"
  • "Sides"
  • "Kids Menu"

Category Description

PropertyValue
Field IDdetails.description
LabelDescription
TypeTextarea
RequiredNo
ValidationOptional string (no max length enforced)

Description: Optional description shown below category name.

Customer Impact:

  • Online Ordering: Shown as subtitle under category name
  • Kiosk: May be displayed on category selection screen

Examples:

  • "Start your meal with our delicious appetizers"
  • "Hand-stretched, wood-fired pizzas"
  • "Freshly made desserts"

Category Image

PropertyValue
Field IDimage
LabelCategory Image
TypeImage Upload
RequiredNo
ValidationJPG, PNG, SVG, WebP; max 10MB

Description: Image representing the category. Used in visual menu layouts.

Customer Impact:

  • Online Ordering: Category thumbnail (if visual menu enabled)
  • Kiosk: Large category image on selection screen

Best Practices:

  • Use appetizing food photos
  • Show representative items from category
  • Consistent style across categories

Parent Category

PropertyValue
Field IDparent_id
LabelParent Category
TypeSelect
RequiredNo

Description: Optional parent category to nest this category underneath, creating a subcategory. The dropdown lists only root (top-level) categories and excludes the category being edited, so the hierarchy is limited to one level of nesting and a category can never be its own parent.

Business Logic:

  • No parent selected → Root (top-level) category
  • Parent selected → Subcategory nested under that parent

Customer Impact

Online Ordering

  1. Navigation: Categories as tabs or sidebar sections
  2. Scrolling: Scroll to category section
  3. Filtering: Click category to filter items
  4. Visual: Category images (if enabled)

Kiosk

  1. Home Screen: Large category buttons
  2. Selection: Tap category to see items
  3. Navigation: Back to categories button
  4. Visual: Category images prominent

Receipt

  • Items grouped by category (optional)
  • Category name may appear as section header

Relations

Depends On

  • Parent Category: A subcategory references a parent category via parent_id (one level of nesting).

Affects

  • Menu Items: Items reference a category through their own category_id.
  • Order Capacity: Category-specific limits reference categories.
  • Reports: Sales by category.

Business Rules

  • A category cannot be deleted if it still contains items; the system returns a 400 error with "Delete failed since the category is currently being used."
  • Category images are processed through media upload and stored as content entities; the resulting content_id is saved on the category record.
  • When a category is updated, the item cache for every item in that category is cleared to ensure ordering channels display the latest data.
  • Category creation, update, and deletion are synced to all active third-party integrations (Square, MplusKassa, etc.) using the category model type and the corresponding event constant.
  • Categories synced one-way from a POS are protected: Kassanet-synced categories cannot be modified or deleted locally, and read-only inbound POS systems (e.g. ShopCaisse) cannot create or delete categories from the back office.
  • The details field merges existing language translations with the new update, preserving translations for languages not included in the current request.

FAQs

  • How do I create a subcategory? When creating or editing a category, choose a Parent Category to nest it underneath. Only root (top-level) categories can be selected as parents, so the hierarchy is limited to one level of nesting.

  • Is there a limit to how many categories I can create? There is no hard limit in the system, but keeping the number manageable is recommended for a good customer browsing experience.

  • What happens if I try to delete a category that still has items? Deletion is blocked. You must reassign or remove every item first, otherwise the system returns "Delete failed since the category is currently being used."

  • "What fields can I actually set when creating a category?" A category has four editable fields: Category Name (required), Description (optional), Parent Category (optional), and an image. There's no menu picker, visibility toggle, availability schedule, or tax-rate field on the category form.

  • "How do I create a subcategory / nest categories?" When creating or editing a category, choose a Parent Category to nest it underneath. The list then shows the hierarchy as an expandable tree, and only root (top-level) categories can be selected as parents.

  • "Why can't I pick a parent category that is itself a subcategory?" The parent dropdown only lists root categories and excludes the category you're editing, so the hierarchy is limited to one level of nesting and a category can never be its own parent.

  • "What image formats and size are allowed for a category image?" Category images accept JPG, PNG, SVG, and WebP up to 10 MB.

  • "Why does a category show a higher item count than the items directly inside it?" Each category in the tree shows both its direct item count and an aggregate count that adds up the items in all of its subcategories, so a parent reflects everything beneath it.

  • "Why can't I delete a category?" Deletion is blocked while the category still has items assigned. Reassign or remove every item first, otherwise you get "Delete failed since the category is currently being used."

  • "I added a translation but my edit didn't wipe the other languages — is that expected?" Yes. Category name and description are stored per language, and saving merges your update with existing translations, so languages you didn't touch are preserved.

  • "Why is the Name (or Parent) field greyed out on some categories?" Categories synced from a POS are locked: Kassanet and Lightspeed K-Series categories lock Name and Parent, and MplusKassa categories lock Name and Description, because those fields are owned by the POS and would be overwritten on the next sync.

  • "I edited a category but nothing changed for customers — why?" After saving, the system clears the cache for every item in that category so ordering channels pick up the change. If you still don't see it, confirm the save succeeded and that the items belong to that category.

  • "Do my categories get pushed to my connected POS / Square?" Yes. Creating, updating, or deleting a category triggers a sync to all active integrations (Square, MplusKassa, etc.); read-only inbound POS systems like Kassanet and ShopCaisse are protected and can't be created/edited/deleted from the back office.

  • "I can't find the Create Category button — why?" It only appears if you have the create-category permission and the location's POS allows catalog creation; a read-only inbound POS hides it.


Troubleshooting

Problem: Category not showing in menu

Causes:

  1. Category has no items
  2. All items in category unavailable

Solutions:

  1. Add items to category
  2. Enable item availability

Problem: Items in wrong category

Causes:

  1. Item assigned to wrong category
  2. Category names confusing

Solutions:

  1. Edit item → Change category
  2. Rename categories for clarity

Problem: Edited category but nothing changed for customers

Causes:

  1. Item cache not yet reflected
  2. Items not actually assigned to this category

Solutions:

  1. Confirm the save succeeded (the system clears the cache for every item in the category on save)
  2. Verify the items belong to that category

Examples

Single Category (create payload)

The store/update endpoint accepts a details object (with name and optional description), an optional parent_id, and an optional image:

json
{
  "details": {
    "name": "Starters",
    "description": "Start your meal with our delicious appetizers"
  },
  "parent_id": null
}

Standard Restaurant Categories

json
{
  "categories": [
    { "details": { "name": "Starters" } },
    { "details": { "name": "Salads" } },
    { "details": { "name": "Main Courses" } },
    { "details": { "name": "Sides" } },
    { "details": { "name": "Desserts" } },
    { "details": { "name": "Drinks" } }
  ]
}

Pizza Restaurant

json
{
  "categories": [
    { "details": { "name": "Classic Pizzas", "description": "Our traditional favorites" } },
    { "details": { "name": "Specialty Pizzas", "description": "Chef's special creations" } },
    { "details": { "name": "Build Your Own", "description": "Create your perfect pizza" } },
    { "details": { "name": "Pasta" } },
    { "details": { "name": "Salads" } },
    { "details": { "name": "Sides & Extras" } },
    { "details": { "name": "Desserts" } },
    { "details": { "name": "Drinks" } }
  ]
}

Subcategories (one level of nesting)

A child category references its parent via parent_id:

json
{
  "categories": [
    { "details": { "name": "Drinks" } },
    { "details": { "name": "Hot Drinks" }, "parent_id": "<drinks_category_id>" },
    { "details": { "name": "Cold Drinks" }, "parent_id": "<drinks_category_id>" }
  ]
}