> ## Documentation Index
> Fetch the complete documentation index at: https://docs.colossal.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Cart

> Create and manage shopping carts with add, update, and remove operations.

The cart can be used with Colossal's hosted checkout or with your own backend and checkout flow.

## CartProvider

Wrap your app in `CartProvider` to manage cart state. It handles cart creation, persistence, and provides actions through context.

```tsx theme={null}
import { CartProvider } from "@colossal-sh/storefront-sdk";

<CartProvider storeUid="your-store-uid" currency="USD">
  {children}
</CartProvider>
```

<ResponseField name="CartProvider" type="component">
  <Expandable title="props">
    <ParamField path="storeUid" type="string" required>
      Your project UID.
    </ParamField>

    <ParamField path="currency" type="string" default="USD">
      Currency code for price formatting.
    </ParamField>

    <ParamField path="storage" type="CartIdStorage" default="localStorageCartIds">
      Storage adapter for cart ID persistence.
    </ParamField>
  </Expandable>
</ResponseField>

## High-level hooks

Use `useCartContext` inside `CartProvider` for the simplest cart integration.

| Hook               | Purpose                                             |
| ------------------ | --------------------------------------------------- |
| `useCartContext()` | Access cart state and actions (add, remove, update) |

```tsx theme={null}
import { useCartContext, formatPrice } from "@colossal-sh/storefront-sdk";

function Cart() {
  const { items, subtotal, currency, itemCount, addItem, removeItem, updateQuantity } = useCartContext();

  return (
    <div>
      <p>{itemCount} items, {formatPrice(subtotal, currency)}</p>
      {items.map((item) => (
        <div key={item.uid}>
          <span>{item.name} x {item.quantity}</span>
          <button onClick={() => updateQuantity(item.uid, item.quantity + 1)}>+</button>
          <button onClick={() => updateQuantity(item.uid, item.quantity - 1)}>-</button>
          <button onClick={() => removeItem(item.uid)}>Remove</button>
        </div>
      ))}
    </div>
  );
}
```

<Note>
  `addItem` automatically creates a new cart if one doesn't exist yet. If the stored cart is no longer valid (e.g., it expired), it creates a fresh cart and retries.
</Note>

## Low-level hooks

Direct control over cart mutations, for use outside `CartProvider`.

| Hook                  | Purpose                   |
| --------------------- | ------------------------- |
| `useCart(cartUid)`    | Fetch a cart by UID       |
| `useCreateCart()`     | Create a new cart         |
| `useAddToCart()`      | Add a product to a cart   |
| `useUpdateCartLine()` | Update line item quantity |
| `useRemoveCartLine()` | Remove a line item        |

## Types

### CartContext

Returned by `useCartContext()`.

<ResponseField name="context" type="CartContext">
  <Expandable title="state">
    <ResponseField name="cartId" type="string | null">
      Current cart UID.
    </ResponseField>

    <ResponseField name="cart" type="Cart | null">
      Raw cart data from the GraphQL query.
    </ResponseField>

    <ResponseField name="items" type="SimpleLineItem[]">
      Cart line items with computed prices.
    </ResponseField>

    <ResponseField name="subtotal" type="number">
      Sum of all line item subtotals.
    </ResponseField>

    <ResponseField name="currency" type="string">
      Currency code.
    </ResponseField>

    <ResponseField name="itemCount" type="number">
      Number of line items.
    </ResponseField>

    <ResponseField name="isLoading" type="boolean">
      Whether the cart is being fetched.
    </ResponseField>

    <ResponseField name="isOpen" type="boolean">
      Whether the cart drawer/modal is open.
    </ResponseField>
  </Expandable>

  <Expandable title="actions">
    <ResponseField name="addItem" type="(productUid: string) => Promise<void>">
      Add a product to the cart. Creates a cart if none exists.
    </ResponseField>

    <ResponseField name="removeItem" type="(lineItemUid: string) => Promise<void>">
      Remove a line item.
    </ResponseField>

    <ResponseField name="updateQuantity" type="(lineItemUid: string, quantity: number) => Promise<void>">
      Update a line item's quantity.
    </ResponseField>

    <ResponseField name="openCart" type="() => void">
      Set `isOpen` to `true`.
    </ResponseField>

    <ResponseField name="closeCart" type="() => void">
      Set `isOpen` to `false`.
    </ResponseField>

    <ResponseField name="refreshCart" type="() => void">
      Clear the stored cart ID.
    </ResponseField>
  </Expandable>
</ResponseField>

### SimpleLineItem

Each item in the `items` array.

<ResponseField name="item" type="SimpleLineItem">
  <Expandable title="properties">
    <ResponseField name="uid" type="string">
      Line item UID.
    </ResponseField>

    <ResponseField name="productUid" type="string">
      Product UID.
    </ResponseField>

    <ResponseField name="name" type="string">
      Product name.
    </ResponseField>

    <ResponseField name="price" type="number">
      Unit price.
    </ResponseField>

    <ResponseField name="currency" type="string">
      Currency code.
    </ResponseField>

    <ResponseField name="imageUrl" type="string">
      First media URL.
    </ResponseField>

    <ResponseField name="quantity" type="number">
      Quantity in cart.
    </ResponseField>

    <ResponseField name="subtotal" type="number">
      Price x quantity.
    </ResponseField>
  </Expandable>
</ResponseField>

## Custom storage

The default `localStorageCartIds` stores cart IDs in `localStorage` keyed by `cart-{storeUid}`. To use a different storage mechanism, implement the `CartIdStorage` interface:

```tsx theme={null}
import { type CartIdStorage, CartProvider } from "@colossal-sh/storefront-sdk";

const customStorage: CartIdStorage = {
  get(storeUid: string): string | null {
    return sessionStorage.getItem(`cart-${storeUid}`);
  },
  set(storeUid: string, cartId: string | null): void {
    if (cartId === null) {
      sessionStorage.removeItem(`cart-${storeUid}`);
    } else {
      sessionStorage.setItem(`cart-${storeUid}`, cartId);
    }
  },
};

<CartProvider storeUid="..." storage={customStorage}>
  {children}
</CartProvider>
```

## Next steps

* [Checkout](/react-sdk/checkout). Convert the cart into an order with payment
* [Cart concepts](/concepts/cart). Understand the cart lifecycle
