Skip to main content
@quickbutik/kit/elements is the same headless composition as the React layer, as custom elements: <qb-product>, <qb-cart>, <qb-checkout-button> and friends. Use it for anything that is not React: a plain HTML page, Astro, Vue, Svelte, Nuxt, a Rails, Laravel or WordPress view, Webflow, an existing jQuery theme.
  • Light DOM, no shadow root. Your stylesheet reaches everything.
  • No markup of their own. The elements bind data into markup you wrote, through data-qb-* attributes, and reflect their state as attributes for your CSS. Four deliberate exceptions: <qb-product-image> renders an <img>, <qb-cart-count> writes its number, <qb-seo> writes into <head>, and <qb-checkout> renders the checkout’s iframe.
  • No CSS shipped. The elements reflect their state as attributes for your own stylesheet.
Do not mix the React layer and the elements on one page. Each brings its own cart store, and the two would not update together.

Choose a setup

One <script> with the key on it configures the shop and registers every element. The page below it is markup only: no init call, no wrapper element.
  • Pin the version in the URL and cache-bust on upgrade.
  • Use defer. The elements cope with being upgraded mid-parse either way; defer keeps the script off the critical path.
  • One self-contained file, no runtime dependencies, exposed as window.Quickbutik.
Every attribute and the window.Quickbutik API are in Scripting and the script tag reference.
Call configure() once, at startup. A second call replaces the ambient client and cart store only for elements mounted afterwards; elements already on the page keep the first ones, so a badge and a drawer stop updating together. Never call it per client-side navigation.

Import it only in the browser

@quickbutik/kit/elements defines classes that extend HTMLElement when it loads. Importing it in Node (an SSR entry, a frontmatter, a server file) throws ReferenceError: HTMLElement is not defined. The root entry @quickbutik/kit is the server-safe one; use it for server-side reads.
Tell your framework’s template compiler that qb-* tags are custom elements, so it does not try to resolve them as components (Vue: compilerOptions.isCustomElement = (tag) => tag.startsWith("qb-")).
For pages that must be indexable, render the catalog HTML on the server with the plain client and use the elements for the interactive parts (cart, variant picker, checkout). See Server-side rendering.

The ambient shop: there is no wrapper element

The shop is ambient: one client and one shared cart store per page, set up once by configure() or by the script tag’s data-publishable-key. Every element finds it on its own. An element that talks to the API and finds no shop reports a named ShopkitConfigError listing the three ways to provide one, sets state="error" and emits qb:error.

<qb-shop>: optional overrides

<qb-shop> exists for the cases a page-wide singleton cannot serve. A <qb-shop> ancestor wins for its own subtree; everything else keeps using the ambient shop.
It emits qb:shop-ready with { client, cartStore, currency, locale }.

Set the currency

Products and carts state the currency their prices are in (product.currency, cart.currency), and the elements format with it. For a shop that sells in its own currency only, nothing needs configuring. currency in configure() (or data-currency on the script tag) is the currency the page browses in: it is sent with every product, cart and checkout request, and a shop that offers that currency answers with converted prices. Leave it out to start in the shop’s own currency. It doubles as the formatting fallback for a platform older than product.currency.
For a shop that offers several currencies, drop in a switcher. A choice reprices every product, list and cart on the page (the same cart, re-read) and is remembered for the next visit, winning over the configured value:
Display versus charge currencies, setCurrency() and the switcher’s templates are covered in Currencies. On by default. A page configured by configure(), <qb-shop> or the script tag gets the kit’s default cookie banner appended to <body> (unless it places its own <qb-consent-banner>), and loads the merchant’s own GA4, GTM and Meta pixel from the shop’s settings only after the shopper agrees. The elements report view_item, search, the cart events and the purchase, and every checkout handoff forwards the shopper’s decision to the hosted checkout.
Your own banner markup, gated content and every option: Consent and analytics.

Next steps

Templates and bindings

Bindings, repeats, actions and styling on state.

Build the storefront

Catalog, product page, cart, checkout and thank-you page.

Scripting

window.Quickbutik, events and recipes.

Elements reference

Every element’s attributes, scope, reflected state and events.