React hooks
30+ hooks from `@cimplify/sdk/react`: typed, cached, and provider-driven. Each requires a `<CimplifyProvider>` ancestor.
Data hooks share a module-scoped cache that survives re-renders. Changing the active location via setCurrentLocation invalidates every cache because pricing is location-aware. Every hook returns { ..., isLoading, error, refetch }.
Catalogue
useProducts
Paginated product list. Filters by category, collection, search query, or featured flag.
const { products, isLoading, pagination, is_complete, refetch } = useProducts({
category: "drinks",
search: "espresso",
featured: true,
limit: 24,
});useProduct
Auto-detects whether the argument is a slug or an ID. IDs use the prod_ prefix.
const { product, isLoading } = useProduct("studio-tee-natural"); // slug
const { product: byId } = useProduct("prod_xyz"); // iduseCategories / useCollections / useCollection
const { categories } = useCategories();
const { collections } = useCollections();
const { collection } = useCollection("col_summer-25");useSearch
const { results, isLoading } = useSearch("oat milk", { limit: 10 });useBundles / useBillingPlans
const { bundles } = useBundles();
const { plans } = useBillingPlans({ productId: "prod_subscription" });Cart
useCart
Optimistic cart state. UI updates instantly; the SDK syncs the mutation to the server in the background and rolls back on error.
| Field | Type |
|---|---|
items | UseCartItem[] |
itemCount | number |
subtotal / tax / total | number |
currency | string |
isEmpty | boolean |
addItem | (product, quantity?, options?: AddToCartOptions) => void |
updateQuantity | (itemId, qty) => void |
removeItem | (itemId) => void |
clearCart | () => void |
sync | () => void |
const { items, total, addItem, updateQuantity, removeItem } = useCart();
addItem(product, 1, {
variantId: "var_studio-tee-natural_size_s",
addOnOptionIds: ["addopt_gift_wrap"],
bundleSelections: [{ productId: "prod_socks", quantity: 1 }],
compositeSelections: [{ groupId: "grp_main", productId: "prod_jollof" }],
specialInstructions: "Please ship without invoice.",
});useCartDrawer
Opens / closes the <CartDrawer> from anywhere in the tree. Requires a <CartDrawerProvider> ancestor. The provider auto-opens the drawer on addItem by default.
const { isOpen, open, close, toggle } = useCartDrawer();useQuote / useProductPrice / useValidateDiscount
Server-priced quote for a product configuration; auto-refreshes 30s before expiry by default.
const { quote, isExpired, refresh, messages } = useQuote(
{
productId: "prod_abc",
variantId: "var_large",
addOnOptionIds: ["addon_oat", "addon_syrup"],
quantity: 2,
},
{ autoRefresh: true, refreshBeforeExpiryMs: 30_000 },
);
const { price } = useProductPrice({ productId: "prod_abc", variantId: "var_large" });
const { result } = useValidateDiscount({ code: "WELCOME10", subtotal: 4200 });Checkout & orders
useCheckout
Submits a flat CheckoutFormData body to POST /checkout. No nested checkout_data wrapper; fields go on the body.
const { process, isLoading } = useCheckout();
const r = await process({
cart_id: cartId,
customer: { name: "Akua", email: "akua@example.com", phone: "+233244000000" },
order_type: "delivery",
payment_method: "card",
delivery_address: { line1: "12 Independence Ave", city: "Accra" },
});
if (r.success) router.push(`/orders/${r.order?.id}`);useOrder / useOrders
useOrder can poll until a terminal status. useOrders lists the signed-in customer's orders.
const { order } = useOrder("ord_abc", { poll: true, pollInterval: 5000 });
const { orders } = useOrders({ status: "completed", limit: 20 });Scheduling
useServices / useAvailableSlots / useServiceAvailability
Variant-aware: pass variant_id to slot lookups when a service has variants (e.g. 30-min vs 60-min haircut). duration_minutes is no longer accepted on getAvailableSlots.
const { services } = useServices();
const { slots } = useAvailableSlots({
service_id: "svc_haircut",
date: "2026-06-01",
variant_id: "var_haircut_60min",
participant_count: 1,
});
const { availability } = useServiceAvailability({
service_id: "svc_haircut",
start_date: "2026-06-01",
end_date: "2026-06-07",
variant_id: "var_haircut_60min",
});useBookings
const { upcoming, past, isLoading } = useBookings({ scope: "all" });Subscriptions, deals, activity, FX
useSubscriptions / useSubscription
const { subscriptions } = useSubscriptions();
const { subscription, pause, resume, cancel } = useSubscription("sub_abc");useDeals / useProductsOnSale / useProductDeals
const { deals } = useDeals();
const { products: onSale } = useProductsOnSale({ limit: 12 });
const { deals: applies } = useProductDeals({ productId: "prod_abc" });useActivityState / useRecommendations
Reads the merged session activity state (recently viewed, dismissable session messages, recommendation lanes) and returns dismissed-message helpers.
const { state, dismissMessage } = useActivityState();
const { recommendations } = useRecommendations({ surface: "home" });useFxRate / useDeliveryFee
const { rate } = useFxRate({ from: "GHS", to: "USD" });
const { fee } = useDeliveryFee({ latitude: 5.55, longitude: -0.196, country: "GH" });Provider context & misc
useCimplify / useCimplifyClient / useBootstrap
useCimplify exposes the merged provider context (business, locations, current location, isReady). useCimplifyClient returns the raw typed client. useBootstrap exposes the in-flight bootstrap promise if you need to await it.
const { business, currency, currentLocation, setCurrentLocation, isReady } = useCimplify();
const client = useCimplifyClient();useChat / useTaxonomies / useAttributeDefinitions / usePropertyFacets
const { messages, send, isPolling } = useChat({ pollInterval: 3000 });
const { taxonomies } = useTaxonomies();
const { facets } = usePropertyFacets({ category: "drinks" });Reference table
| Hook | Returns | Notes |
|---|---|---|
useProducts | products, pagination, is_complete | Filters: category, collection, search, featured, limit. |
useProduct | product | Slug or prod_ ID. |
useCategories | categories | |
useCollections / useCollection | collections | collection | |
useBundles | bundles | |
useSearch | results | Server-side ranking. |
useCart | items, total, addItem, ... | Optimistic. |
useCartDrawer | open, close, toggle, isOpen | Needs CartDrawerProvider. |
useQuote / useProductPrice | quote, refresh | Auto-refreshes near expiry. |
useValidateDiscount | result | Validates a coupon against subtotal. |
useCheckout | process, isLoading | Flat CheckoutFormData. |
useOrder / useOrders | order | orders | Polling supported on useOrder. |
useServices | services | |
useAvailableSlots | slots | Variant-aware. |
useServiceAvailability | availability | Date-range scan. |
useBookings | upcoming, past | |
useSubscriptions | subscriptions | Pause / resume / cancel. |
useDeals / useProductsOnSale / useProductDeals | deals | products | |
useActivityState / useRecommendations | state | recommendations | Session-bound. |
useFxRate | rate | |
useDeliveryFee | fee | Lat/lng + country. |
useTaxonomies / useTaxonomy / useTaxonomyPath | taxonomies | taxonomy | |
useAttributeDefinitions / usePropertyFacets | definitions | facets | Faceted filtering. |
useChat | messages, send, isPolling | Powers <ChatWidget>. |
useLocations | locations | |
useVariantSelector | axisSelections, selectedVariant | State machine for multi-axis variants. |
Where next
-
React overview Provider, app shell, the hook+component split.
-
Components Pages and primitives, with key props.
-
Server Components For pre-fetching from the App Router.
-
Cart API The flat
cart.addItemshape behinduseCart.
Component catalog
90+ React components ship in `@cimplify/sdk/react`. This page covers the page components you mount on routes, the cart drawer, and the most-used primitives. Every component is also [ejectable](/docs/cli/components) via ` cimplify add <name>` when you need full control.
Server Components
`@cimplify/sdk/server` is a Node-only entry for the Next.js App Router. It ships three things: a request-memoized client factory, a typed cache-tag scheme, and Server Action revalidation helpers.