Skip to main content

AI Prompts for Commerce Engine

Copy these prompts into your AI coding assistant (Claude, Cursor, Copilot, etc.) to generate production-quality Commerce Engine code. Each prompt includes the right context for accurate results.
For best results, install the Commerce Engine skills package in your project, or paste the LLM docs URL so your assistant can fetch live API details.
Type import rule: All prompts assume types are imported directly from the SDK package (e.g., import type { Cart, Product, CreateCartBody } from "@commercengine/storefront-sdk"), never hand-written. If the AI generates custom interfaces for API types, ask it to use the SDK’s named exports instead. See Importing Types for details.

Foundation Context

Prepend this block to any prompt for best results. It gives the AI the essential Commerce Engine knowledge that every task depends on.
You are working with the Commerce Engine TypeScript SDK (@commercengine/storefront-sdk).

Essential rules:
1. SDK Response Pattern: All SDK methods return { data, error, response }. Always check error before using data.
   The SDK automatically unwraps the API's "content" envelope — access fields directly on data (e.g., data.products, data.cart, data.user), NOT data.content.
2. Token Lifecycle: Every user (even anonymous) needs tokens. The first step is always creating an anonymous session. After login, the SDK receives new privileged tokens. On logout, the API returns NEW anonymous tokens (not just clears them).
3. Type Imports: Always import types directly from "@commercengine/storefront-sdk" (or "-nextjs"). Never define custom interfaces for API schemas. All schema types and operation types are available as named exports.
4. variant_id Rule: variant_id is ALWAYS required in cart operations. Pass null for products without variants.
5. Cart Creation: POST /carts REQUIRES at least one item. You cannot create an empty cart. First add uses createCart(), subsequent adds use addDeleteCartItem().
6. Cart Merge: When an anonymous user logs in, their cart automatically merges into the logged-in user's account. Do not re-create or re-fetch carts manually after login.
7. Error Shape: Errors have { message: string, success: boolean, code: string }. Common HTTP status codes: 400 (bad request), 401 (unauthorized), 403 (forbidden), 404 (not found), 500 (server error), 502 (bad gateway). Always check error before using data.

SDK client structure: sdk.auth, sdk.catalog, sdk.cart, sdk.customer, sdk.order, sdk.payments, sdk.helpers, sdk.storeconfig

Type lookup (fetch for exact TypeScript definitions):
  curl -H "Accept: text/markdown" https://llm-docs.commercengine.io/storefront/schemas/{SchemaName}
  curl -H "Accept: text/markdown" https://llm-docs.commercengine.io/storefront/operations/{operation-name}.md

Type Lookup

Look Up a Schema Definition

I need the exact TypeScript definition for the Commerce Engine Cart type.
Fetch it from: curl -H "Accept: text/markdown" https://llm-docs.commercengine.io/storefront/schemas/Cart

Then show me how to import and use this type in my code. Remember: always import directly from the SDK package as a named export, never define custom interfaces:

import type { Cart } from "@commercengine/storefront-sdk";

Look Up an SDK Method Signature

I need the exact TypeScript signature and usage example for the createCart SDK method.
Fetch it from: curl -H "Accept: text/markdown" https://llm-docs.commercengine.io/storefront/operations/create-cart.md

Show me the full method call with proper typing. Import operation types directly from the SDK:

import type { CreateCartBody, CreateCartContent } from "@commercengine/storefront-sdk";

SDK Setup

Initialize SDK (React / Vue / SPA)

Set up the Commerce Engine TypeScript SDK for a client-side React app.

Requirements:
- Use @commercengine/storefront-sdk
- Import and use Environment enum (Environment.Production or Environment.Staging) — do NOT hardcode strings
- Use BrowserTokenStorage for automatic token persistence
- Use environment variables for storeId and apiKey (REACT_APP_ prefix for CRA, VITE_ prefix for Vite)
- Export the SDK instance from lib/storefront.ts
- Include onTokensUpdated callback (to sync auth state) and onTokensCleared callback (to redirect on session loss)
- On app init, call sdk.auth.getAnonymousToken() to create an anonymous session — this is REQUIRED before any other API call will work
- The anonymous session gives the user a user_id, access_token, and refresh_token

Anti-patterns to avoid:
- Do NOT make API calls before establishing an anonymous session — they will return 401
- Do NOT hardcode "production" or "staging" as strings — use the Environment enum

Reference:
  curl -H "Accept: text/markdown" https://llm-docs.commercengine.io/storefront/operations/get-anonymous-token.md

Initialize SDK (Next.js App Router)

Set up the Commerce Engine Next.js SDK for an App Router project.

Requirements:
- Use @commercengine/storefront-sdk-nextjs
- Create lib/storefront.ts that re-exports the storefront function
- Add <StorefrontSDKInitializer /> in the root layout — this handles automatic anonymous token creation
- In root layout, use storefront({ isRootLayout: true }) — the isRootLayout flag is required
- Show how to use storefront() in client components (no cookies needed)
- Show how to use storefront(cookies()) in server components and server actions
- Environment variables: NEXT_PUBLIC_STORE_ID, NEXT_PUBLIC_API_KEY, NEXT_PUBLIC_ENVIRONMENT
- Add NEXT_BUILD_CACHE_TOKENS=true to next.config.ts for efficient token reuse during SSG/ISR builds

Create a .env.local template:
  NEXT_PUBLIC_STORE_ID=your-store-id
  NEXT_PUBLIC_API_KEY=your-api-key
  NEXT_PUBLIC_ENVIRONMENT=production
  NEXT_BUILD_CACHE_TOKENS=true

Anti-patterns to avoid:
- Do NOT call auth endpoints from Server Components — they MUST be in Server Actions or API Routes
- Do NOT forget to pass cookies() in server contexts — it breaks user session continuity

Reference: https://llm-docs.commercengine.io/sdk/

Initialize SDK (Node.js Backend)

Set up the Commerce Engine SDK for a Node.js Express backend.

Requirements:
- Use @commercengine/storefront-sdk with MemoryTokenStorage
- Configure for server-side usage with proper timeout
- Show middleware that creates per-request SDK instances — this is critical for token isolation between concurrent users
- The middleware should extract the Bearer token from the request Authorization header and pass it to MemoryTokenStorage
- Include health check endpoint using sdk.helpers.retrieveAllCountries()
- Show how to handle the case where no Bearer token is present (create anonymous session)

Reference: https://llm-docs.commercengine.io/sdk/

Authentication

Email OTP Login Flow

Implement a complete email OTP login flow using the Commerce Engine SDK.

IMPORTANT PREREQUISITE: The user MUST already have an anonymous session before calling loginWithEmail. If using the Next.js SDK with StorefrontSDKInitializer, this is handled automatically. For SPAs, call sdk.auth.getAnonymousToken() on app init.

Steps:
1. Call sdk.auth.loginWithEmail({ email, register_if_not_exists: true })
   - Response: { data, error } where data contains otp_token and otp_action
   - Access: data.otp_token, data.otp_action (NOT data.content.otp_token)
2. Show OTP input UI
3. Call sdk.auth.verifyOtp({ otp, otp_token: data.otp_token, otp_action: data.otp_action })
   - On success: data contains user, access_token, refresh_token
   - The SDK automatically stores the new tokens if tokenStorage is configured
4. After verification, the user object has is_anonymous: false, is_logged_in: true

Requirements:
- Handle both login and registration (register_if_not_exists: true)
- Show loading states during API calls
- Handle errors for each step (invalid email, wrong OTP, expired OTP)
- Use the { data, error } pattern, not try/catch
- Include a "Resend OTP" button that calls loginWithEmail again
- After successful login, the user's anonymous cart automatically merges into their account

Anti-patterns to avoid:
- Do NOT try to log in without an anonymous session first — it will 401
- Do NOT access data.content.otp_token — the SDK unwraps content, use data.otp_token directly

Reference: fetch these for exact signatures:
  curl -H "Accept: text/markdown" https://llm-docs.commercengine.io/storefront/operations/login-with-email.md
  curl -H "Accept: text/markdown" https://llm-docs.commercengine.io/storefront/operations/verify-otp.md

Phone OTP Login Flow

Implement a phone number OTP login flow using the Commerce Engine SDK.

IMPORTANT PREREQUISITE: The user MUST already have an anonymous session.

Steps:
1. Call sdk.auth.loginWithPhone({ phone, country_code, register_if_not_exists: true })
   - country_code format: string with "+" prefix, e.g., "+91", "+1", "+44"
   - Response: data.otp_token, data.otp_action
2. Show OTP input UI
3. Call sdk.auth.verifyOtp({ otp, otp_token: data.otp_token, otp_action: data.otp_action })

Requirements:
- Include country code selector dropdown (use sdk.helpers.retrieveAllCountries() for the list)
- Country code must include the "+" prefix (e.g., "+91" for India, "+1" for US)
- Handle errors for each step
- Use { data, error } pattern
- Include "Resend OTP" button
- After successful login, anonymous cart merges automatically

Reference: fetch these for exact signatures:
  curl -H "Accept: text/markdown" https://llm-docs.commercengine.io/storefront/operations/login-with-phone.md
  curl -H "Accept: text/markdown" https://llm-docs.commercengine.io/storefront/operations/verify-otp.md

Next.js Server Action Auth

Implement Commerce Engine authentication as Next.js Server Actions.

Requirements:
- Add "use server" directive at the top of the server action file
- Import: import { storefront } from "@commercengine/storefront-sdk-nextjs" and import { cookies } from "next/headers"
- Create server actions for: sendOTP (email), verifyOTP, logout
- Use storefront(cookies()) in every server action for token persistence
- Use redirect() after successful auth
- IMPORTANT: Auth endpoints that return tokens MUST be in Server Actions or API Routes, NOT Server Components
- Server actions should return { success: boolean, error?: string } to the client
- On error, return the error message to the client — do NOT throw

Example server action structure:
  "use server"
  import { storefront } from "@commercengine/storefront-sdk-nextjs";
  import { cookies } from "next/headers";

  export async function sendOTP(email: string) {
    const sdk = storefront(cookies());
    const { data, error } = await sdk.auth.loginWithEmail({ email, register_if_not_exists: true });
    if (error) return { success: false, error: error.message };
    return { success: true, otp_token: data.otp_token, otp_action: data.otp_action };
  }

Reference: https://llm-docs.commercengine.io/sdk/

Product Catalog

Product Listing Page

Build a product listing page using the Commerce Engine SDK.

Requirements:
- Fetch products with sdk.catalog.listProducts()
- Response shape: data.products (array of Product) and data.pagination
- Support pagination (page, limit query params)
- Support filtering by category_id or category_slug
- Display: product name, images[0].url (for the primary image), selling_price, slug
- Link each product to /products/[slug]
- Handle loading and error states
- Use { data, error } pattern
- Import types directly from SDK: import type { Product, ListProductsContent } from "@commercengine/storefront-sdk"

Variant handling on PLP:
- Check the has_variant flag on each product
- For products with has_variant: true, show variant indicators (e.g., color swatches from variant_options)
- Consider using the default variant's price/image for the listing card
- Alternative approach: use sdk.catalog.listSkus() which returns pre-flattened Items (product_id + variant_id) — simpler for PLPs where you want each variant as its own card

Anti-patterns to avoid:
- Do NOT render all products identically — check has_variant and handle variant display
- Do NOT access data.content.products — use data.products directly

Reference: fetch for exact response shape and TypeScript definitions:
  curl -H "Accept: text/markdown" https://llm-docs.commercengine.io/storefront/operations/list-products.md
  curl -H "Accept: text/markdown" https://llm-docs.commercengine.io/storefront/schemas/Product

Product Detail Page (Next.js SSG)

Build a statically generated product detail page in Next.js App Router using Commerce Engine.

Requirements:
- Use generateStaticParams() to pre-render product pages from sdk.catalog.listProducts()
- Fetch product detail with sdk.catalog.getProductDetail({ product_id_or_slug: slug })
- Response shape: data.product (a ProductDetail object)
- Display: name, description, images (loop over images array, show images[n].url), price, variants, availability
- Use storefront() without cookies for build context (build context has no cookie jar, uses memory storage internally)
- Configure NEXT_BUILD_CACHE_TOKENS=true in .env for efficient token reuse during builds
- Set revalidation for ISR: export const revalidate = 3600 (or your preferred interval)

Variant selection UI:
- If product.has_variant is true, fetch variants with sdk.catalog.listProductVariants({ product_id })
- Display variant_options as selectors (e.g., color swatches, size buttons)
- When user selects options, find the matching variant from the associated_options
- Update the displayed price, image, and stock based on the selected variant
- The selected variant_id is needed for add-to-cart

AddToCart button (client component):
- Must pass both product_id AND variant_id (null if no variants) to cart operations
- First add creates the cart (sdk.cart.createCart), subsequent adds use sdk.cart.addDeleteCartItem

Reference: fetch for exact response shape:
  curl -H "Accept: text/markdown" https://llm-docs.commercengine.io/storefront/operations/get-product-detail.md
  curl -H "Accept: text/markdown" https://llm-docs.commercengine.io/storefront/operations/list-product-variants.md
Implement product search using the Commerce Engine SDK.

Requirements:
- Use sdk.catalog.searchProducts({ query: { q: searchTerm } })
- IMPORTANT: Search returns Items (SKUs), not Products — each result has product_id and variant_id
- Response includes facet_distribution for building filter UI (category, brand, price range, etc.)
- Debounce search input (300ms)
- Show search results with product name, image, price
- Display facet filters alongside results for refinement
- Handle empty results and errors
- Support keyboard navigation of results

Reference: fetch for exact signature:
  curl -H "Accept: text/markdown" https://llm-docs.commercengine.io/storefront/operations/search-products.md

Cart & Checkout

Shopping Cart

Build a complete shopping cart using the Commerce Engine SDK.

CRITICAL RULES:
- POST /carts (createCart) REQUIRES at least one item — you CANNOT create an empty cart
- First item add: use sdk.cart.createCart({ items: [{ product_id, variant_id, quantity }] })
- Subsequent item adds: use sdk.cart.addDeleteCartItem({ id: cartId }, { product_id, variant_id, quantity }) — NOTE: two arguments (path params object + body object)
- variant_id is ALWAYS required — pass null for products without variants
- When a user logs in, their anonymous cart automatically merges into their account — do NOT manually re-create carts

Requirements:
- Fetch existing cart with sdk.cart.getUserCart({ user_id: userId }) — returns 404 if no active cart exists, handle gracefully
- Implement two-phase cart logic: check if cart exists (getUserCart), if not, use createCart on first add; if yes, use addDeleteCartItem
- Update quantity by calling addDeleteCartItem with the new total quantity
- Remove items by setting quantity to 0
- Display: cart_items, quantities, selling_price, subtotal, items_tax_amount, shipping_amount, grand_total, to_be_paid
- Delete entire cart with sdk.cart.deleteCart({ id: cartId })
- Import types directly from SDK: import type { Cart, CartItem, UpdateCartItem } from "@commercengine/storefront-sdk"

Coupon considerations:
- Some coupons require the user to be logged in — applying a login-required coupon with an anonymous token will fail
- Prompt users to log in before applying coupons if they are anonymous

Anti-patterns to avoid:
- Do NOT try to create an empty cart — POST /carts requires items
- Do NOT re-create carts after login — carts merge automatically
- Do NOT access data.content.grand_total — use data.cart.grand_total

Reference: fetch for exact TypeScript definitions and signatures:
  curl -H "Accept: text/markdown" https://llm-docs.commercengine.io/storefront/operations/create-cart.md
  curl -H "Accept: text/markdown" https://llm-docs.commercengine.io/storefront/operations/update-cart.md
  curl -H "Accept: text/markdown" https://llm-docs.commercengine.io/storefront/schemas/Cart
  curl -H "Accept: text/markdown" https://llm-docs.commercengine.io/storefront/schemas/UpdateCartItem

Apply Coupon / Promotions

Implement coupon and promotion handling for the Commerce Engine cart.

Requirements:
- Apply coupon: sdk.cart.applyCoupon({ id: cartId }, { coupon_code: "CODE" }) — NOTE: two arguments (path params object + body object)
- Remove coupon: sdk.cart.removeCoupon({ id: cartId }) — one argument (path params object)
- List available coupons: sdk.cart.listCoupons()
- List available promotions: sdk.cart.listPromotions()
- Show discount breakdown in cart summary (coupon_discount_amount, promotion_discount_amount)
- Handle invalid/expired coupon errors
- IMPORTANT: Some coupons require the user to be logged in. If the user is anonymous and a coupon requires login, the API returns a 400 error. Show a "Please log in to use this coupon" message.

Reference: fetch for exact signatures:
  curl -H "Accept: text/markdown" https://llm-docs.commercengine.io/storefront/operations/apply-coupon.md
  curl -H "Accept: text/markdown" https://llm-docs.commercengine.io/storefront/operations/list-coupons.md

Checkout Flow

Implement checkout for a Commerce Engine storefront.

RECOMMENDED APPROACH: Use the Commerce Engine Hosted Checkout — a pre-built, embeddable checkout that handles cart, authentication, address collection, payments, and order confirmation inside an iframe. This is the fastest and most reliable way to add checkout.

Hosted Checkout setup:
- Install: npm install @commercengine/checkout (React/Vue/Svelte/Solid) or @commercengine/js (vanilla)
- Initialize once: const { addToCart, openCart, openCheckout, destroyCheckout } = initCheckout({ storeId, apiKey, environment, onComplete, onCartUpdate })
- Open cart: openCart() — shows cart drawer
- Open checkout directly: openCheckout() — no arguments, skips cart, goes to checkout
- Add to cart: addToCart(productId, variantId, quantity) — positional args, variantId can be null
- Cleanup: destroyCheckout() — call when unmounting the component
- Auth sync (if your app handles auth): use authMode: "provided" and call updateTokens(accessToken, refreshToken) when tokens change
- Callbacks: onComplete({ id, orderNumber }), onCartUpdate({ count, total, currency }), onLogin(), onLogout() — passed in initCheckout config, NOT .on() event listeners

For React:
  import { initCheckout, useCheckout } from "@commercengine/checkout/react";
  // Call initCheckout() once at app entry
  // Use useCheckout() hook in components for openCart, openCheckout, addToCart, etc.

For details on all framework integrations, configuration options, and events, see:
  https://commercengine.io/docs/hosted-checkout/overview

IMPORTANT: The user MUST be logged in before creating an order. Anonymous users cannot check out. Use OTP auth with register_if_not_exists: true for a seamless login-before-checkout experience.

ALTERNATIVE: Custom Checkout (only if you need full UI control)
If you must build a custom checkout, the flow is:
1. Authenticate user (required): sdk.auth.loginWithEmail({ email, register_if_not_exists: true }) → sdk.auth.verifyOtp(...)
2. Update cart address: sdk.cart.createCartAddress({ id: cartId }, { shipping_address, billing_address })
   - For logged-in users: can use billing_address_id / shipping_address_id for saved addresses
   - This returns updated cart with recalculated shipping and totals — re-render cart summary
3. Validate pincode: sdk.cart.checkPincodeDeliverability({ cart_id: cartId, delivery_pincode: pincode })
4. Create order: sdk.order.createOrder({ cart_id, payment_method: { payment_provider_slug: "JUSPAY", integration_type: "hyper-checkout", action: "paymentPage", return_url: "https://yourstore.com/checkout/return", gateway_reference_id: "optional_pg_id" } })
   - NOTE: uses payment_method (single object), NOT payment_gateway + payment_gateway_params
   - Response: data.order, data.payment_required, data.payment_info
5. Redirect user to: data.payment_info.payment_links.web (Juspay payment page)
6. On return to your return_url, POLL payment status:
   - Call sdk.order.getPaymentStatus(orderNumber) immediately — takes a STRING, not an object
   - If status is "pending" or "partially_paid", wait 3 seconds and poll again
   - Continue polling until "success" or "failed" (timeout after 1-2 minutes)
   - NEVER trust payment gateway callback URL parameters alone
7. If status is "failed" and is_retry_available is true:
   - Show "Retry Payment" button
   - Call sdk.order.retryOrderPayment({ order_number }, { payment_method: { payment_provider_slug: "JUSPAY", integration_type: "hyper-checkout", action: "paymentPage", return_url: "..." } })
   - NOTE: two arguments — path params object + body object
   - Redirect to new payment URL and repeat polling

Anti-patterns to avoid:
- Do NOT trust payment gateway callbacks as the final status — always poll the API
- Do NOT skip pincode serviceability check — orders to unserviceable areas will fail
- Do NOT forget to re-render cart summary after address update (shipping costs change)

Reference: fetch for exact signatures:
  curl -H "Accept: text/markdown" https://llm-docs.commercengine.io/storefront/operations/create-order.md
  curl -H "Accept: text/markdown" https://llm-docs.commercengine.io/storefront/operations/create-cart-address.md
  curl -H "Accept: text/markdown" https://llm-docs.commercengine.io/storefront/operations/get-payment-status.md
  curl -H "Accept: text/markdown" https://llm-docs.commercengine.io/storefront/operations/retry-payment.md

Hosted Checkout Integration

Integrate the Commerce Engine Hosted Checkout into my app.

The Hosted Checkout is a pre-built, iframe-based checkout that handles the entire purchase flow — cart, auth, address, payments, and order confirmation.

Requirements:
- Install: npm install @commercengine/checkout (for React/Vue/Svelte/Solid)
- Initialize once at app entry: const { addToCart, openCart, openCheckout, destroyCheckout } = initCheckout({ storeId, apiKey, environment, onComplete, onCartUpdate })
- Add an "Add to Cart" button that calls addToCart(productId, variantId, quantity) — positional args
  - variantId can be null for products without variants
- Add a "View Cart" button that calls openCart()
- Add a "Buy Now" button that calls openCheckout() — no arguments
- Show a cart badge with item count using onCartUpdate callback ({ count, total, currency })
- Handle order completion with onComplete callback ({ id, orderNumber })
- Clean up: call destroyCheckout() when the component unmounts

Auth mode (passed in initCheckout config):
- Default (authMode: "managed"): Checkout handles its own login/registration via OTP
- If your app already handles CE auth, use authMode: "provided":
  - Pass initial tokens: initCheckout({ ..., authMode: "provided", accessToken, refreshToken })
  - Sync token changes: call updateTokens(accessToken, refreshToken) whenever your app refreshes tokens
  - Listen for onLogin and onLogout callbacks to sync auth state back to your app
- IMPORTANT: If your app uses Commerce Engine auth (loginWithEmail, verifyOtp, etc.), you MUST use authMode: "provided". Otherwise both your app and checkout will manage separate sessions.

Quick Buy (direct purchase):
- Use quickBuy config: initCheckout({ ..., quickBuy: { productId, variantId, quantity } })
- sessionMode: "continue-existing" (default, adds to existing cart) or "force-new" (fresh cart)

Framework-specific setup:
- React: import { initCheckout, useCheckout } from "@commercengine/checkout/react" — useCheckout() returns { openCart, openCheckout, addToCart, destroyCheckout, isReady, cart }
- Vue: import { useCheckout } from "@commercengine/checkout/vue" — composable with reactive refs
- Svelte: import from "@commercengine/checkout/svelte" — readable stores
- Solid: import { useCheckout } from "@commercengine/checkout/solid" — fine-grained signals
- Vanilla JS: import from "@commercengine/js" — initCheckout() returns methods directly

Reference:
  https://commercengine.io/docs/hosted-checkout/overview
  https://commercengine.io/docs/hosted-checkout/configuration

Customer Account

Customer Profile & Order Management

Build a customer account area using the Commerce Engine SDK. This includes profile, addresses, order history, cancellations, and returns.

Requirements:

Profile:
- Fetch user details: sdk.auth.getUserDetails({ id: userId })
  - Response: data.user with email, phone, is_logged_in, login_methods, etc.
- Update user: sdk.auth.updateUser({ id: userId }, { first_name, last_name })
- Fetch customer detail: sdk.customer.getCustomer({ id: userId })

Address Book:
- List addresses: sdk.customer.listAddresses({ user_id: userId })
  - Each address has is_default_billing and is_default_shipping flags
- Create address: sdk.customer.createAddress({ user_id: userId }, addressData)
- Update address: sdk.customer.updateAddress({ user_id: userId, address_id: addressId }, updates)
- Delete address: sdk.customer.deleteAddress({ user_id: userId, address_id: addressId })

Order History:
- List orders: sdk.order.listOrders() — returns paginated order list
- Order detail: sdk.order.getOrderDetail({ order_number }) — returns full OrderDetail
- Shipments: sdk.order.listShipments({ order_number })
- Payments: sdk.order.listPayments({ order_number })

Order Cancellation:
- IMPORTANT: Check is_cancellation_allowed flag on OrderDetail before showing cancel button
- Cancel: sdk.order.cancelOrder({ order_number }, { cancellation_reason, refund_mode })
  - refund_mode: "original_payment_mode" or "bank_transfer"
  - If bank_transfer, also pass bank_account_id

Order Returns:
- Returns are currently managed by store administrators through the Admin Portal
- There is no storefront SDK method for customers to initiate returns
- Customers can cancel orders (if is_cancellation_allowed is true) but not request returns from the storefront
- Return APIs for the storefront are under development

Loyalty Points:
- Fetch loyalty: sdk.customer.getLoyaltyDetails({ user_id: userId })

Reference: fetch for exact signatures:
  curl -H "Accept: text/markdown" https://llm-docs.commercengine.io/storefront/operations/get-user-detail.md
  curl -H "Accept: text/markdown" https://llm-docs.commercengine.io/storefront/operations/list-addresses.md
  curl -H "Accept: text/markdown" https://llm-docs.commercengine.io/storefront/operations/list-orders.md
  curl -H "Accept: text/markdown" https://llm-docs.commercengine.io/storefront/operations/cancel-order.md

Webhooks

Webhook Handler

Set up webhook handlers for Commerce Engine events.

Requirements:
- Create an Express/Next.js API route that receives POST requests from Commerce Engine
- Handle these webhook events: order.created, order.confirmed, order.cancelled, payment.successful, payment.failed, shipment.created, shipment.delivered
- Verify webhook signatures using HMAC-SHA256:
  - Extract the signature from the request header
  - Compute HMAC-SHA256 of the raw request body using your webhook secret
  - Compare the computed hash with the received signature
  - Reject requests with invalid signatures
- Process events asynchronously (push to a queue for background processing)
- Return 200 immediately to acknowledge receipt — do not do heavy processing synchronously
- Log webhook payloads for debugging
- Handle duplicate events idempotently (store processed event IDs)

Reference: fetch for webhook payload schemas:
  curl -H "Accept: text/markdown" https://llm-docs.commercengine.io/webhooks/
  curl -H "Accept: text/markdown" https://llm-docs.commercengine.io/storefront/webhooks/order.created

Full Application

Complete Next.js Storefront

Scaffold a complete Next.js App Router storefront using Commerce Engine.

Requirements:
- Use @commercengine/storefront-sdk-nextjs
- Use @commercengine/checkout for the checkout experience (Hosted Checkout)

Project structure (App Router):
  app/
    layout.tsx              — Root layout with StorefrontSDKInitializer, storefront({ isRootLayout: true })
    page.tsx                — Homepage with featured products and categories
    products/
      page.tsx              — Product listing with filters and pagination (server component)
      [slug]/page.tsx       — Product detail with variant selection (SSG with generateStaticParams)
    account/
      page.tsx              — Customer profile (protected, redirect if not logged in)
      orders/page.tsx       — Order history
      orders/[id]/page.tsx  — Order detail with cancel/return actions
      addresses/page.tsx    — Address book management
    auth/
      actions.ts            — Server actions: sendOTP, verifyOTP, logout (with "use server")
  components/
    AddToCartButton.tsx     — Client component, handles first-add (createCart) vs subsequent (addDeleteCartItem)
    CartButton.tsx          — Opens hosted checkout cart with openCart()
    AuthForm.tsx            — Email/phone OTP login form
    ProductCard.tsx         — Product card for listings
    VariantSelector.tsx     — Variant option selector (color, size, etc.)
  lib/
    storefront.ts           — Re-export storefront function

Key patterns:
- Auth: Email OTP login via Server Actions in app/auth/actions.ts
- SSG: Pre-render product pages with generateStaticParams + revalidate for ISR
- Cart: Use Hosted Checkout — initCheckout() in root layout, openCart()/openCheckout() from buttons
- Token caching: NEXT_BUILD_CACHE_TOKENS=true for build optimization
- Error handling: Use { data, error } pattern everywhere
- Middleware: Add middleware.ts to protect /account routes (check for logged-in tokens)

Full SDK reference: https://llm-docs.commercengine.io/
API operations: https://llm-docs.commercengine.io/operations/
Hosted Checkout: https://commercengine.io/docs/hosted-checkout/overview

React Context + Hooks Setup

Create a complete React context and hooks setup for Commerce Engine.

Requirements:
- CommerceProvider: Initializes SDK instance and shares via context, calls getAnonymousToken() on mount
- AuthProvider: Manages auth state (user, isLoggedIn, login, logout, loading)
- useCart hook:
  - State: cart, itemCount, loading
  - Methods: addItem, updateItem, removeItem, clearCart
  - IMPORTANT: addItem must handle two-phase cart logic:
    - If no cart exists yet, call sdk.cart.createCart({ items: [...] }) — cart creation requires at least one item
    - If cart already exists, call sdk.cart.addDeleteCartItem({ id: cartId }, { product_id, variant_id, quantity })
  - After login, re-fetch cart (it merged automatically) — use sdk.cart.getUserCart({ user_id })
  - For good UX, update state optimistically then reconcile with the server response
- useProducts hook: fetch products with filters, pagination, loading state
- All hooks use { data, error } pattern from SDK
- Import ALL types directly from the SDK — never define custom interfaces:
  import type { Cart, Product, CartItem, UpdateCartItem } from "@commercengine/storefront-sdk";
  import type { CreateCartBody, ListProductsContent } from "@commercengine/storefront-sdk";

Reference: https://llm-docs.commercengine.io/sdk/
Fetch type definitions: curl -H "Accept: text/markdown" https://llm-docs.commercengine.io/storefront/schemas/Cart

Pro tip: When using these prompts, paste the relevant curl commands so your AI assistant can fetch the latest API schemas directly. This ensures the generated code matches the current API exactly.