# Cart (https://docs.salla.dev/twilight/react/routes/cart)



<Callout title="Framework: TanStack Start">
  This page is written for TanStack Start, the default and currently supported framework. [See what depends on the framework](https://docs.salla.dev/twilight/react/start/frameworks).
</Callout>

The customer sees what they added, can change quantities, apply a coupon or loyalty points, and continue to checkout. Guests and signed-in customers both see it. Customise this route to change how cart lines and the summary look.

## URL [#url]

| Pattern            | Example              |
| ------------------ | -------------------- |
| `/{-$locale}/cart` | `/cart` · `/ar/cart` |

The only param is the optional `locale` ([locale prefix](https://docs.salla.dev/twilight/react/routes/home#locale-prefix)). There are no search params.

### Try it [#try-it]

This is the cart as the engine renders it, running against the demo store. Switch the language or the width.

<RoutePreview path="/cart" pattern="/{-$locale}/cart" />

## Route file [#route-file]

```tsx title="app/routes/cart.tsx"
// @auto-generated
import { createFileRoute } from '@tanstack/react-router';
import { Cart } from '@salla.sa/twilight-theme-engine/routes/cart';
import type { CartPageProps } from '@salla.sa/twilight-theme-engine/routes/cart';
import { CartSkeleton } from '@salla.sa/twilight-theme-engine/skeleton';
import { withHead } from '@salla.sa/twilight-theme-engine/tanstack';

export const Route = createFileRoute('/{-$locale}/cart')({
  loader: ({ params }): Promise<CartPageProps> => Cart.loader({ locale: params.locale }),
  head: withHead(Cart),
  pendingComponent: () => <CartSkeleton />,
  component: CartComponent,
});

function CartComponent() {
  const data: CartPageProps = Route.useLoaderData();
  return <Cart.Component {...data} />;
}
```

Delete the `// @auto-generated` line to own the file.

### A customised version [#a-customised-version]

Same engine loader, head and skeleton, with your own page component. `CartPage` here is a component you write in `app/components/cart/CartPage.tsx`; it receives the loader data (`CartPageProps`). To use your own file for `/cart`, point the path at it from `app/routes.ts` (see [Fork a built-in route](https://docs.salla.dev/twilight/react/recipes/fork-a-built-in-route)).

```tsx title="app/routes/cart-page.tsx"
import { createFileRoute } from '@tanstack/react-router';
import { Cart } from '@salla.sa/twilight-theme-engine/routes/cart';
import type { CartPageProps } from '@salla.sa/twilight-theme-engine/routes/cart';
import { CartSkeleton } from '@salla.sa/twilight-theme-engine/skeleton';
import { withHead } from '@salla.sa/twilight-theme-engine/tanstack';
import { CartPage } from '../components/cart/CartPage';

export const Route = createFileRoute('/{-$locale}/cart')({
  loader: ({ params }): Promise<CartPageProps> => Cart.loader({ locale: params.locale }),
  head: withHead(Cart),
  pendingComponent: () => <CartSkeleton />,
  component: CartComponent,
});

function CartComponent() {
  const data: CartPageProps = Route.useLoaderData();
  return <CartPage {...data} />;
}
```

## What it loads [#what-it-loads]

The loader returns only `{ page: { slug, title } }`. The cart itself is not loaded on the server, because the cart id lives in the browser. After the page mounts, the component reads the current cart id from the Salla SDK, fetches that cart, and shows `CartSkeleton` until it has it. Your own component does the same if it needs cart data; for live updates see [React to cart events](https://docs.salla.dev/twilight/react/recipes/react-to-cart-events).

## Head and SEO [#head-and-seo]

Title is the translated "Cart", plus hreflang links. There is no description, canonical or Open Graph tag.

## Edge cases [#edge-cases]

* **Empty cart.** The page shows "Your cart is empty" with a link home.
* **Skeleton in the server HTML.** The server always sends the skeleton for `/cart`, since the cart is browser-only. This is expected.
* **Extending the loader.** `Cart.loader` takes an optional `extend` callback, but only a synchronous result is merged; an async one is ignored.
* **Hook slots.** `cart:start`, `cart:items.start`, `cart:items.end` and `cart:end` let you add content without forking ([hook slots](https://docs.salla.dev/twilight/react/guide/hooks-and-slots)).

## See also [#see-also]

* [React to cart events](https://docs.salla.dev/twilight/react/recipes/react-to-cart-events)
* [Thank you page](https://docs.salla.dev/twilight/react/routes/thank-you)
* [Fork a built-in route](https://docs.salla.dev/twilight/react/recipes/fork-a-built-in-route)
* [Routes overview](https://docs.salla.dev/twilight/react/routes)
