Categories, Menu & Labels
Category tree, navigation menu, detail, and product labels
Categories
Category Tree
const { categories } = await client.catalog.getCategories('cs');
// Hierarchical tree with childrenCategory Detail
const category = await client.catalog.getCategory('electronics', 'cs');
// { id, name, slug, description, image, children }Category Products
const {data: products, error} = await client.catalog.getCategoryProducts('electronics', {
page: 1,
limit: 12,
sort: 'newest',
});getCategoryProducts accepts the same ProductsQuery filters as getProducts: price bounds (including zero), stock, rating, search, labels, IDs, exclusions, parameters, facets and visitor locale/currency/country. Arrays remain repeated query parameters and parameter/facet selections are JSON. Invalid page zero is sent to validation instead of silently becoming page one. The route category remains the category scope.
Navigation Menu
Merchants build their storefront navigation in the admin under Navigace (Menu Builder). Fetch a resolved menu by its handle (the primary menu is "main"):
const { data: menu, error } = await client.catalog.getMenu('main', { locale: 'cs' });
if (error || !menu) {
// 404 for an unknown or inactive handle. Fall back to the category tree.
const { categories } = await client.catalog.getCategories('cs');
}The response is a tree of items, each already resolved to a link target in the requested locale:
{
"handle": "main",
"name": "Hlavní menu",
"locale": "cs",
"items": [
{
"id": "01J...",
"type": "CATEGORY",
"label": "Elektronika",
"description": null,
"url": null,
"ref": { "type": "CATEGORY", "slug": "elektronika" },
"badgeText": "Sleva",
"badgeTone": "SALE",
"badgeColor": null,
"badgeTextColor": null,
"labelColor": null,
"icon": "tag",
"isHighlighted": true,
"openInNewTab": false,
"imageUrl": "https://.../tile.jpg",
"children": [ /* same shape, up to depth 3 */ ]
}
]
}Item types and how to build the link:
type | Link target |
|---|---|
CATEGORY | your category route, from ref.slug (e.g. /category/elektronika) |
PAGE | your CMS page route, from ref.slug |
PRODUCT | your product route, from ref.slug |
COLLECTION | your collection listing, from ref.slug |
LINK | item.url verbatim (an arbitrary URL; ref is null) |
For typed items (CATEGORY/PAGE/COLLECTION/PRODUCT) the target is ref, which resolves to { type, slug } at read time, so category, page and product renames flow through automatically without touching the menu. imageUrl is a processed tile image for mega-menu layouts. Inactive items and items whose target was deleted are skipped server-side, so you only ever render live links.
Item styling
Every node (including nested children) carries presentation fields the merchant sets in the admin. They are advisory: render what fits your template, ignore the rest, and defaults stay inert so an unstyled item looks exactly as before.
| Field | Type | Meaning |
|---|---|---|
badgeText | string | null | Chip label next to the item (e.g. "Novinka"). No chip when null. |
badgeTone | "NEUTRAL" | "SALE" | "NEW" | "ACCENT" | Preset that maps to your palette. Always present. Suggested mapping: SALE to your sale color, NEW to a success color, ACCENT to your primary, NEUTRAL to the current text color. |
badgeColor | string | null | Custom badge background hex. When set, it overrides badgeTone. |
badgeTextColor | string | null | Custom badge text hex. |
labelColor | string | null | Custom hex for the item label text. Null inherits your link color. |
icon | string | null | A lucide icon slug (kebab-case, e.g. shopping-bag) to render before the label. Map it to your own icon set; unknown slugs render no icon. |
isHighlighted | boolean | Emphasize the item (bold or accent). |
openInNewTab | boolean | LINK items only: open the target in a new tab (target="_blank" rel="noopener"). Always false on typed items. |
Custom hex colors are merchant-authored, so applying them via an inline style is the intended, legitimate use:
function MenuBadge({ item }: { item: MenuItem }) {
if (!item.badgeText) return null;
const custom = item.badgeColor || item.badgeTextColor;
const toneClass = {
NEUTRAL: 'badge--neutral',
SALE: 'badge--sale',
NEW: 'badge--new',
ACCENT: 'badge--accent',
}[item.badgeTone];
return (
<span
className={custom ? undefined : toneClass}
style={
custom
? { backgroundColor: item.badgeColor ?? undefined, color: item.badgeTextColor ?? undefined }
: undefined
}
>
{item.badgeText}
</span>
);
}
// LINK items honoring the new-tab flag:
const linkProps = item.openInNewTab ? { target: '_blank', rel: 'noopener' } : {};Labels
Labels are tags you can attach to products (e.g. "New", "Sale", "Bestseller"):
const { labels } = await client.catalog.getLabels('cs');
// [{ id, name, slug, color }]Featured Products
Curated products highlighted by the admin:
const featured = await client.catalog.getFeatured({
locale: 'cs',
currency: 'CZK',
});