@commercengine/storefront package for React SPAs. Keep the SDK factory in one module, use the public accessor for catalog reads, and initialize one live session for cart, authentication, account, and order flows.
Installation
Configure the storefront
src/lib/storefront.ts
Root bootstrap
Establish the anonymous session once when the application starts. Public catalog rendering does not need to wait for this call.src/providers.tsx
ensureAccessToken() is safe to centralize at startup. Do not repeat it before every session method.Public catalog queries
src/hooks/use-products.ts
searchProducts() rather than listProducts() when the page needs facets, filtering, or search. The search response contains flattened sellable Items/SKUs.
Hosted Checkout: recommended cart and checkout
Hosted Checkout supplies cart, login, addresses, fulfilment, discounts, payment, and confirmation. When the React app also uses the Storefront SDK, the Storefront SDK must own the session. Update the storefront configuration to send SDK token changes to checkout:src/lib/storefront.ts
src/storefront-bootstrap.tsx
src/components/cart-button.tsx
src/components/add-to-cart-button.tsx
Custom authentication UI
Build custom auth only when the storefront needs login state outside Hosted Checkout, such as account, order, loyalty, or saved-address pages. An OTP form has two explicit steps:sdk.clearTokens() after successful logout.
Custom cart: advanced
Use a custom cart only when the storefront needs a fully custom cart/checkout UI. Hosted Checkout already handles these concerns.First add versus later mutations
Commerce Engine does not create an empty cart.addDeleteCartItem() accepts the desired total quantity, not a delta. Call this helper inside the serialized mutation queue with the latest returned cart, so repeated Add to Cart actions increment the existing line rather than resetting it to 1.
Serialize cart mutations
Every mutation returns the full updated cart. Concurrent mutations can race and overwrite local state with an older response. Queue mutations with concurrency1 or use an async mutex.
Query shape
cart.cart_items and use cart.to_be_paid as the final amount. Check expires_at when restoring a persisted cart ID.
Product detail state
For products with variants:- use option query parameters as canonical URL state
- resolve a variant only when all option keys match its
associated_options - disable impossible or unavailable combinations
- keep Add to Cart disabled until the selected variant is purchasable
- pass the selected
variant.id
variant_id: null.
See Catalog and the production starters for the full model.
Error and loading states
A production React storefront should distinguish:- first load from background refresh
- empty result from request failure
- confirmed 404 from transient server failure
- checkout not ready from checkout error
- anonymous user from invalid session
{ data, error, response } result inside each query function.
Production checklist
React production examples
Compare the Vite React storefronts with the Next.js and TanStack Start implementations to separate React component patterns from framework rendering patterns.