Skip to main content
The root entry @quickbutik/kit (or the slimmer /sdk) has no runtime dependencies and works in any runtime with fetch. Use it when you render the DOM yourself, already have a state library, or run on a server.
Before rendering everything by hand, have a look at the web components. They cover the catalog, the variant picker, the cart, checkout and the thank-you page with markup only, and they share the same cart store you’ll use below. You can mix them freely with the client on one page.

1. Load the SDK

.env.local

2. Create one client

src/kit.ts
Create one client per page load in the browser and one per request on the server, because the cookie jar belongs to a request. Clients are cheap. In a browser the cart id is remembered in document.cookie (qb_cart_id for 30 days, qb_checkout_session for 24 hours, and qb_currency once the shopper picks a currency), falling back to localStorage and then memory. If a cart doesn’t survive a reload, check kit.runtime.persistent. See Storage & SSR.
Money is always an integer in minor units (öre, cents): 24900 is 249,00 kr. Every response states the currency its amounts are in (product.currency, cart.currency), so format with that and keep CURRENCY only as a fallback. A shopper can browse in another currency the shop offers: see Currencies.

3. Verify the key

Before building pages, make sure the key and environment work:
A ShopkitScopeError, a 403 carrying required_scopes, or a 401 on every call points at the key or at an apiUrl override. See Troubleshooting.

4. A shared cart store

A header badge, a cart drawer and a cart page should read one observable cart. The kit’s CartStore is framework-free, and the easiest way to get one in browser code is from configure() in the elements entry. It needs no React and no registered elements:
src/cart-state.ts
With the script tag, the same store is Quickbutik.cart and the client is Quickbutik.client.
configure() also sets up the page’s cookie consent: it appends the kit’s default banner to <body> and loads the shop’s analytics once the shopper agrees, and the cart store reports add_to_cart / remove_from_cart into it. Pass consent: { lang: "sv", privacyPolicyUrl: "/integritetspolicy" } to shape the banner, or consent: false to turn it all off. See Consent and analytics.
The shopper’s currency switches through the same client: kit.setCurrency("EUR") reprices every later read, and the store re-reads the same cart in the new currency. See Currencies. Mutations capture errors into error and resolve null instead of throwing. pending counts the mutations in flight.
Call configure() once at startup. A second call replaces the client and store for elements mounted afterwards, while anything already on the page keeps the first ones.

5. Handle errors

A missing resource is not an error. products.get(), getBySlug(), categories.get(), cart.get(), cart.current() and checkout.getSession() resolve to null. See Errors.

Next

Build the storefront

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

Server-side

Node, Hono, Express, Astro and Workers.