Skip to content
Guides

Checkout

Use the framework-generated checkout and understand its actual requirements.

The framework already generates these routes:

  • /checkout/ redirects to /cart.
  • /checkout/:checkoutId renders the purchase flow.
  • /thank-you renders the confirmation.

Do not create pages/checkout.* or pages/thank-you.tsx; those routes are reserved.

Requirements

Checkout always calls useAuth and useCart, even when the store allows guest checkout. Your layout must mount both providers:

layout.tsx
import { AuthProvider, CartProvider, defineLayout } from "@ecomiq/storefront";
import { authClient } from "./lib/auth-client";

export default defineLayout(({ children, settings }) => (
  <AuthProvider client={authClient}>
    <CartProvider
      storeId={settings.store.id}
      currencyCode={settings.store.currency}
    >
      {children}
    </CartProvider>
  </AuthProvider>
));

You also need:

  • lib/auth-client.ts with createStorefrontAuthClient.
  • The pages/api/$.ts proxy.
  • The pages/api/auth.$.ts handler.

The accounts guide includes those files.

Send the shopper to checkout

import { Link, useCart } from "@ecomiq/storefront";

export function CheckoutButton() {
  const { cart } = useCart();

  if (!cart) return null;

  return (
    <Link to="/checkout/$checkoutId" params={{ checkoutId: cart.id }}>
      Continue to checkout
    </Link>
  );
}

Checkout reads settings.store.checkoutSettings.general.allowGuestCheckout. If guest checkout is disabled and no session exists, it redirects to /login?redirect=/checkout/{id}. You must create the /login and /register pages.

Low-level API

For an alternative flow, serverApi exposes the real operations. Each receives one object that includes cartId:

await serverApi.patchCartBuyer({
  cartId,
  email: "andrea@example.com",
  firstName: "Andrea",
  lastName: "Ramos",
  phone: "+1 555 0100",
});

const shipping = await serverApi.getShippingOptions({
  cartId,
  postalCode: "10001",
});

const rate = shipping.groups[0]?.rates[0];
if (rate) {
  await serverApi.putCartShippingMethod({
    cartId,
    rateId: rate.rateId,
    shippingMethodId: rate.shippingMethodId,
  });
}

const result = await serverApi.checkoutCart({
  cartId,
  paymentMethodCode: "bank_transfer",
  externalRef: crypto.randomUUID(),
});

getCartCheckout, patchCartAddresses, uploadPaymentReceipt, addCartPromotionCode, and removeCartPromotionCode are also available.

Stripe and Mercado Pago

The included UI opens a redirect URL when returned by the API and supports manual receipts. It does not yet mount an embedded Stripe or Mercado Pago UI when the provider returns only a clientSecret. Test the selected payment method end to end before publishing.

On this page