Cart
The shopping cart page with line items, offers, coupon and the order summary.
Framework: TanStack Start
This page is written for TanStack Start, the default and currently supported framework. See what depends on the framework.
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
| Pattern | Example |
|---|---|
/{-$locale}/cart | /cart · /ar/cart |
The only param is the optional locale (locale prefix). There are no search params.
Try it
This is the cart as the engine renders it, running against the demo store. Switch the language or the width.
/ar/cartOpen/{-$locale}/cart- locale = ar
- path = /cart
Route file
// @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
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).
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
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.
Head and SEO
Title is the translated "Cart", plus hreflang links. There is no description, canonical or Open Graph tag.
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.loadertakes an optionalextendcallback, but only a synchronous result is merged; an async one is ignored. - Hook slots.
cart:start,cart:items.start,cart:items.endandcart:endlet you add content without forking (hook slots).