---
title: Menu Data Source
slug: experience/menu-data-source
docTags: 
createdAt: 2026-05-12T15:27:26.880Z
---

## Overview

The `menu` data source fetches menu items from the Catalog API. Menus are defined and managed by editors in the CMS, and this data source makes them available to navigation components in the app.

## When to use this

Use `menu` when navigation items should be controlled by editors through the CMS rather than hardcoded in `views.json`. If the navigation is static and never changes, use `custom` instead.

## Basic Example

```json
{
    "type": "menu",
    "contextKey": "mainNav",
    "filter": {
        "name": { "value": "main-navigation" }
    }
}
```

## Configuration

### Type-specific properties

| Property     | Type   | Default | Description                                                            |
| ------------ | ------ | ------- | ---------------------------------------------------------------------- |
| filter       | object | —       | Selects which menu to load (server-side, filters on the menu itself)   |
| itemFilter   | object | —       | Filters items within the loaded menu (client-side, evaluated per item) |
| fetchOptions | object | —       | Optional fetch request options (e.g. `totalCount: false`)              |

For common properties (`contextKey`, `limit`, `batchSize`, etc.) see [Data Sources Overview](docId\:fuMBUaBWeON_OTO5wfevf)

### filter properties (MenuFilter — selects the menu)

| Filter key | Type         | Description                    |
| ---------- | ------------ | ------------------------------ |
| name       | StringFilter | Match menus by name            |
| properties | MapFilter    | Match menus by custom property |

Supports `AND` and `OR`. Does **not** support `condition` — use `itemFilter` for conditional logic.

### itemFilter properties (StorefrontMenuItemFilter — filters items within the menu)

| Filter key | Type         | Description                                |
| ---------- | ------------ | ------------------------------------------ |
| name       | StringFilter | Include only items matching this name      |
| parentId   | StringFilter | Include only items under a specific parent |
| properties | MapFilter    | Filter items by custom property            |

Supports `AND`, `OR`, and `condition`.

## Advanced Features

### Filtering items by condition

Use `itemFilter` with a `condition` to hide menu items based on context:

```json
{
    "type": "menu",
    "contextKey": "mainNav",
    "filter": { "name": { "value": "main-navigation" } },
    "itemFilter": {
        "condition": {
            "value": "$context.user.isLoggedIn",
            "operation": "EQUALS",
            "compareValue": "true"
        }
    }
}
```

## Testing Notes / Edge Cases

- **Menu is selected by&#x20;**`filter.name`: There is no `menuId` property. A wrong name returns an empty list silently.
- `filter`**&#x20;vs&#x20;**`itemFilter`: `filter` runs server-side to select which menu to load. `itemFilter` runs client-side per item. Only `itemFilter` supports `condition`.
- **Item order**: Items are sorted client-side by their `sortIndex` field — the API does not guarantee order. The final order always reflects the `sortIndex` set in the CMS.
- **Editor updates**: Menu changes are subject to `maxCacheAge` — changes may not be immediately visible.
- **Empty menu**: A menu with no items (or all items filtered out) returns an empty list.

## Related Topics

- [Data Sources Overview](docId\:fuMBUaBWeON_OTO5wfevf)
