Appearance
Commerce
Chapter 6. Rendering produced a page; a store also needs a cart, a login, and a checkout. This chapter is the pluggable commerce layer that supplies them.
Ratio doesn't own a commerce backend — it's pluggable. There are two seams: a resolver seam (read-side data into pages) and a provider seam (interactive cart / login / checkout). GoKwik is the first backend behind both.
The resolver seam (read — data into pages)
A page template declares dataSources; the renderer resolves them through an injected BindingResolver.
packages/builder-core/src/commerce/resolve.ts— theBindingResolverinterface +resolvePage(...)(interpolate route params → fan-out fetch → inject into sections → union cache tags) +StubResolver(deterministic sample data for local dev/tests).resolve-shopkit.ts— the realShopkitResolverover@shopkit/data-layer's custom backend adapter. Dispatches each data-source type to aCommerceClientmethod; products pass through unmodified (prices in paise — display shaping is deferred to render, never in the fetch layer).DATA_SOURCE_TYPES(page-builder/doc.ts):PRODUCT,PRODUCTS,PRODUCTS_BY_HANDLES,COLLECTION,COLLECTION_BY_HANDLES,COLLECTIONS,MENU,STATIC.- Boot factory —
storefrontResolver(env)returns the real resolver when theCOMMERCE_*URLs are set, else the stub; in production it throws rather than boot on sample data (the "Sample product N went live" guard).
Connecting a store to a backend
Two inputs combine:
Per-tenant creds (DB):
tenant.commerce = { merchantId, storeId? }— set via the admin commerce route, verified by probing the backend. Shape inpackages/data-repo.Platform-global service URLs (env): one backend serves every merchant. The origin/admin task defs inject
COMMERCE_{PRODUCT,CART,ORDER,NAV,CUSTOMER,SEARCH}_API_URL. The GoKwik service-prefix map:Env var GoKwik URL Service COMMERCE_PRODUCT_API_URLgkx.gokwik.co/psproduct COMMERCE_CART_API_URL/COMMERCE_ORDER_API_URLgkx.gokwik.co/osorder + cart (same /os)COMMERCE_NAV_API_URLgkx.gokwik.co/pi/pcnavigation / menus COMMERCE_CUSTOMER_API_URLgkx.gokwik.co/cscustomer If the URLs aren't set the origin logs
gokwik_config_incompleteand (in prod) refuses to serve samples.
The provider seam (interactive — cart / login / checkout)
Storefront interactivity is chosen per store, per capability — packages/storefront-integrations. How the active provider is resolved for each capability:
- Capabilities:
cart,login,checkout,account,search.composeStorefront(ctx, integrations)resolves the single active provider per capability (the store's explicit pick if enabled, else the first usable vendor, else a first-party native fallback), and returnshead/bodyEndHTML + a unioned CSP + theactiveCart/activeAccount/activeSearchids the origin dispatches on. —registry.ts,compose.ts,csp.ts - GoKwik providers:
side-cart/— the KwikCart hosted drawer (the drawer is the cart; there's no cart page). Bridges the server cart token into the widget via a JS-readableX-Cart-Tokencookie.kwikpass/— KwikPass phone+OTP login; persists thert_kp_atcookie (holding the GoKwik access token) so the server can fetch order/account data, then refreshes the account island.checkout/— the GoKwik checkout SDK; captures order completion viapostMessage(origin-pinned to gokwik.co/.io) and redirects to/order-confirmation.
- Native fallbacks exist for cart / account / search when no vendor is active.
KwikPass ⟂ checkout are independent
Login (KwikPass) and checkout are separate toggles, each gated on its own env/config — a store isn't switched to KwikPass login just because it can sell. Don't consolidate them.
Origin commerce handlers
The interactive endpoints (all no-store) — apps/origin/src/handlers/:
cart.ts—POST /cart/add·/cart/update; resolves the variant server-side, sets the cart cookies, returns a re-rendered drawer fragment / JSON / a 303 (no-JS).account.ts— login-gated; fetches profile / order history / addresses using the KwikPass access-token cookie; 3-tier render fallback (templates/account.json→sections/main-account.liquid→ built-in).order.ts— the order-confirmation / thank-you page; clears cart cookies.search.ts— native product search behind theactiveSearchseam.POST /checkout(inindex.ts) — the server-side GoKwikcreateCheckouthandshake.
Cart-token cookies
Three cookies, easy to conflate: an httpOnly server cart cookie, a JS-readable X-Cart-Token mirror for the GoKwik widget, and a rt_cart_present marker for the native cart. storeCartCookies / readableCartCookie / expireCartPresentCookie are the source of truth.
Note
@shopkit/data-layer (the canonical product/cart/order shapes + the custom-adapter contract) is an external npm dependency, not in-repo. The account-data.ts / search-data.ts fetchers hit /cs and the search service directly, outside the data-layer client.