CommerceForAI

Cart (React)

A cart for any React site, in three pieces. The hooks handle the parts that are easy to get wrong: current prices, stock checks, option combinations, a secret-safe checkout, and emptying the cart after payment. They draw nothing, so the cart looks like the rest of your site.

1. The checkout route

Your server creates the checkout, so the API key never reaches the browser. The browser only sends variant ids and quantities; prices come from CommerceForAI.

// app/api/checkout/route.ts (Next.js). Also works in Hono, Remix, Astro, SvelteKit, Bun and Deno.
import { createCheckoutHandler } from "commerceforai";

export const POST = createCheckoutHandler(); // success page: /checkout/success

2. Components you own

Copy in a cart drawer, an add-to-cart button with an option picker, and the checkout route. They use Tailwind; restyle them however you like.

npx shadcn@latest add https://commerceforai.com/r/cart.json
// app/layout.tsx
import { CartProvider } from "commerceforai/react";
<CartProvider>{children}</CartProvider>

// header (server component): pass the catalog so the cart shows names, prices and stock
const { data } = await commerce.products.list({ active: true, limit: 100 });
<CartButton products={data.data} />

// product page
<AddToCart product={product} />

// app/checkout/success/page.tsx
<ClearCartOnSuccess />

3. Or just the hooks

"use client";
import { useCart, useVariantPicker, formatMoney } from "commerceforai/react";

const cart = useCart(products);
cart.add(variantId, 1);                   // merges with an existing line
cart.lines;                               // joined to the catalog: product, variant, line_total, over_stock
cart.subtotal; cart.count; cart.missing;  // missing = products that were removed
await cart.checkout({ discount_code });   // posts to /api/checkout and redirects to Stripe

const picker = useVariantPicker(product);
picker.options;   // [{ name: "Size", values: [{ value: "M", available: true, selected: true }] }]
picker.select("Size", "L");
picker.variant;   // the matching variant, or null until every option is chosen
picker.inStock;

The cart is saved in the browser and synced across tabs. A checkout that fails on stock returns { type: "out_of_stock", variant_id, available } in cart.error; cart.fix() trims the cart to what's available. Not using React? The same logic ships framework-free as commerceforai/cart.