LLM Docs Header: All requests to https://llm-docs.commercengine.io must include the Accept: text/markdown header (or append .md to the URL path). Without it, responses return HTML instead of parseable markdown.
Custom SSR Bindings (@commercengine/ssr-utils )
Prerequisite: SDK initialized. See setup/ .
When to Use This Skill
Use @commercengine/ssr-utils only for frameworks that do not have a first-party Commerce Engine wrapper:
Framework What to Use
Next.js @commercengine/storefront/nextjs → see ssr-patterns/
TanStack Start @commercengine/storefront/tanstack-start → see ssr-patterns/
SvelteKit @commercengine/ssr-utils → this skill
Nuxt @commercengine/ssr-utils → this skill
Astro (SSR) @commercengine/ssr-utils → this skill
Why This Matters
The SDK model splits public reads from live session flows:
-
PublicStorefrontSDK / storefront.public() for public build/prerender reads
-
SessionStorefrontSDK / storefront.session(...) for live anonymous or logged-in user flows
@commercengine/ssr-utils exists only for the second case. It provides cookie-backed request storage for building custom framework bindings.
Quick Reference
Concept What It Does
CookieAdapter
Normalizes framework cookie APIs into { get, set, delete }
ServerTokenStorage
Implements TokenStorage using any CookieAdapter
createCookieAdapter(...)
Helper for frameworks whose cookie store already has compatible get / set / delete methods
Decision Tree
User Request: "Add SSR support" / "Cookie-based auth" / "Server-side rendering" │ ├─ Next.js? │ └─ YES → Use @commercengine/storefront/nextjs → see ssr-patterns/ │ ├─ TanStack Start? │ └─ YES → Use @commercengine/storefront/tanstack-start → see ssr-patterns/ │ ├─ Public build/prerender read? │ └─ YES → Use PublicStorefrontSDK / storefront.public() │ ├─ Live request with cookies? (SvelteKit, Nuxt, Astro, etc.) │ └─ Create CookieAdapter → ServerTokenStorage → SessionStorefrontSDK │ └─ Optional: wrap the base config in your own framework helper
Architecture
Public render / prerender └─ PublicStorefrontSDK └─ API key only └─ No token bootstrap, refresh, or cookie writes
Live SSR request └─ SessionStorefrontSDK └─ tokenStorage: ServerTokenStorage(adapter) └─ Reads and writes request cookies └─ Can bootstrap anonymous auth and refresh tokens
Installation
npm install @commercengine/storefront @commercengine/ssr-utils
Key Patterns
- Build the CookieAdapter
SvelteKit
const adapter = { get: (name: string) => cookies.get(name) ?? null, set: (name: string, value: string, options?: Parameters<typeof cookies.set>[2]) => cookies.set(name, value, options), delete: (name: string) => cookies.delete(name), };
Nuxt / h3
import { deleteCookie, getCookie, setCookie } from "h3";
const adapter = { get: (name: string) => getCookie(event, name) ?? null, set: (name: string, value: string, options?: Parameters<typeof setCookie>[3]) => setCookie(event, name, value, options), delete: (name: string) => deleteCookie(event, name), };
Astro (SSR)
const adapter = { get: (name: string) => Astro.cookies.get(name)?.value ?? null, set: (name: string, value: string, options?: Parameters<typeof Astro.cookies.set>[2]) => Astro.cookies.set(name, value, options), delete: (name: string) => Astro.cookies.delete(name), };
- Create ServerTokenStorage
import { ServerTokenStorage } from "@commercengine/ssr-utils";
const tokenStorage = new ServerTokenStorage(adapter, { prefix: "myapp_", maxAge: 2592000, path: "/", sameSite: "lax", });
- Create the session SDK
import { SessionStorefrontSDK } from "@commercengine/storefront";
const sdk = new SessionStorefrontSDK({ storeId: "your-store-id", apiKey: "your-api-key", tokenStorage, });
- Public render SDK
For build-time or public SSR reads, do not go through ServerTokenStorage at all:
import { PublicStorefrontSDK } from "@commercengine/storefront";
const publicSdk = new PublicStorefrontSDK({ storeId: "your-store-id", apiKey: "your-api-key", });
const { data } = await publicSdk.catalog.listProducts();
- Session bootstrap
If a custom SSR binding wants to establish the session eagerly at the start of a live request, use the session SDK:
await sdk.ensureAccessToken(); const { data } = await sdk.cart.getWishlist();
For ordinary session-aware SDK calls such as sdk.cart.getWishlist() , sdk.cart.addToWishlist() , sdk.cart.getUserCart() , or sdk.customer.listAddresses() , you do not need to call ensureAccessToken() first. The session middleware and overloads handle session creation and user_id / customer_id resolution automatically.
Hosted Checkout Token Sync (SSR)
If Hosted Checkout is present, the Storefront SDK should remain the session owner. Wire onTokensUpdated so the checkout runtime stays in sync on the client side.
const sdk = new SessionStorefrontSDK({ storeId: "...", apiKey: "...", tokenStorage, onTokensUpdated: (accessToken, refreshToken) => { if (typeof window !== "undefined") { import("@commercengine/checkout").then(({ getCheckout }) => { getCheckout().updateTokens(accessToken, refreshToken); }); } }, });
Common Pitfalls
Level Issue Solution
CRITICAL Using BrowserTokenStorage in SSR code Use ServerTokenStorage
CRITICAL Using session SDK for build/prerender public pages Use PublicStorefrontSDK or storefront.public()
HIGH Using ssr-utils directly in Next.js or TanStack Start Use the first-party wrappers: @commercengine/storefront/nextjs or @commercengine/storefront/tanstack-start
HIGH Client and server cookie formats drifting Keep prefix, path, secure, sameSite, and encoding aligned
MEDIUM Scattering ensureAccessToken() across feature code If you want eager bootstrap, centralize it in one request bootstrap/helper instead of calling it before every cart/auth/customer method
See Also
-
setup/
-
SDK installation and framework detection
-
ssr-patterns/
-
First-party SSR patterns for Next.js and TanStack Start
-
auth/
-
Authentication flows
-
cart-checkout/
-
Hosted Checkout sync details
Documentation
-
Token Management: https://www.commercengine.io/docs/sdk/token-management
-
LLM Reference: https://llm-docs.commercengine.io/sdk/