Behio Storefront SDK
Catalog & Products

Categories, Menu & Labels

Category tree, navigation menu, detail, and product labels

Categories

Category Tree

const { categories } = await client.catalog.getCategories('cs');
// Hierarchical tree with children

Category Detail

const category = await client.catalog.getCategory('electronics', 'cs');
// { id, name, slug, description, image, children }

Category Products

const products = await client.catalog.getCategoryProducts('electronics', {
  page: 1,
  limit: 12,
  sort: 'newest',
});

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:

typeLink target
CATEGORYyour category route, from ref.slug (e.g. /category/elektronika)
PAGEyour CMS page route, from ref.slug
PRODUCTyour product route, from ref.slug
COLLECTIONyour collection listing, from ref.slug
LINKitem.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.

FieldTypeMeaning
badgeTextstring | nullChip 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.
badgeColorstring | nullCustom badge background hex. When set, it overrides badgeTone.
badgeTextColorstring | nullCustom badge text hex.
labelColorstring | nullCustom hex for the item label text. Null inherits your link color.
iconstring | nullA 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.
isHighlightedbooleanEmphasize the item (bold or accent).
openInNewTabbooleanLINK 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 }]

Curated products highlighted by the admin:

const featured = await client.catalog.getFeatured({
  locale: 'cs',
  currency: 'CZK',
});

On this page