Shortcodes & Tags
Join Markt is not Shopify Liquid. Developers use four surfaces:- Nunjucks tags —
{% markt_component %},{% markt_snippet %} - Nunjucks context + filters —
products,store,shopUrl,formatPrice, … - Helpers —
helpers.components.products.getItemsByIds(items, ids) - HTML embed attributes —
data-markt-*buy buttons on external sites - Vite / React — TypeScript + storefront API (no template tags)
MARKT_NUNJUCKS_API_VERSION 1.0.0 — see Nunjucks Theme API.
Display products (Nunjucks)
Homepage / products grid (groups-aware)
PrefercatalogItems so group cards appear once and grouped products are not duplicated:
buildMarktStorefrontContext(). Use standaloneProducts for ungrouped-only lists; use full products for detail pages and group members.
Featured by id or slug
Limit for homepage
Current product page
Ontemplates/product.njk, use product (or null if missing).
Platform tags
Legacy imported themes may use
{% render_component %} / {% render_snippet %} via the optional markt.sellauth extension — native themes should use markt_* only.
Core filters
Cart (theme + platform)
Cart source of truth: browserlocalStorage key cart (appCart).
- Add:
appCart.add(productId, variantId, quantity)— skip whenproduct.visibility == 'on-hold' - Resolve lines:
GET /api/v1/cart?storeId=&shopId=&cart= - Checkout: theme
checkout()usingappCart.items→POST /api/v1/checkout→/checkout/{orderId}
product.image, product.slug, variant.quantityMin). There is no {% markt_cart %} tag — cart is JS + API.
Embed buy shortcodes (external HTML)
For merchant sites outside the theme (Webflow, custom HTML). Load the embed script, then use product CUID attributes — not Liquid tags.
JS API:
Markt.init(), Markt.open({ items, theme }), Markt.close().
Dashboard → product → Embed Checkout generates snippets. Demo: /embed/demo.html.
Vite / React (no {% %} shortcodes)
Anti-patterns
- Inventing Shopify-style
{% product_grid %}Liquid tags - Looping raw
productsfor the homepage when groups exist (duplicates) - Allowing Add to cart on
visibility === 'on-hold' - Putting
| jsoninsidex-data="..."or HTML attributes without encoding - Dumping full product descriptions into
<head>scripts - Redefining
Alpine.data('cartPage') - Hardcoding prices that ignore the catalog API
- Custom card payment forms inside the theme
- Calling
/api/dashboard/*from the public storefront - Using SellAuth snake_case field names in native themes