Storefront overview

Country-aware catalog, cart, checkout, confirmation, and account routes in Openfront E-commerce.

The built-in storefront lives under app/(storefront)/[countryCode]. Screens are in features/storefront/screens, UI in features/storefront/modules, and GraphQL calls in features/storefront/lib/data.

Country routing

proxy.ts hands storefront requests to features/storefront/middleware.ts. It loads regions and their countries, then picks a country code from the URL, the Vercel geo header, NEXT_PUBLIC_DEFAULT_REGION (default us), or the first region. Requests without a country code are redirected, so / becomes /us. While the database has no users, every page redirects to /dashboard/init.

Routes

Route under /[countryCode]ScreenCustomer journey
/HomePageHome page with store title and description
/storeStorePageAll products, sortable by price through getProductsSortedByPrice
/categories/[...category]CategoryPageCategory listing
/collections/[handle]CollectionPageCollection listing
/products/[handle]ProductPageProduct detail with options and regional price. Only published products are readable.
/cartCartPageCart lines, quantities and discount codes
/checkoutCheckoutPageAddress, shipping method, payment, review
/order/confirmed/[id]OrderConfirmedPageConfirmation. Guests use the order secretKey.
/account (login slot)LoginPageSign in and register
/account (dashboard slot)AccountDashboardPageOverview
/account/profile, /account/addressesAccountProfilePage, AccountAddressesPageProfile, password and saved addresses
/account/orders, /account/orders/details/[id]AccountOrdersPage, AccountOrderDetailsPageOrder history and detail
/account/invoicingAccountInvoicingPageBusiness account request form, account balance, unpaid items, invoice creation and payment, customer token
/account/invoicesAccountInvoicesPagePaid invoices
/account/checkout-linkinline pagesLegacy checkout link. See limitations.

Cart identity

createActiveCart returns a signed cart proof. The storefront stores it in the _openfront_cart_id cookie (httpOnly) and sends it as the x-openfront-cart-proof header. Cart operations call assertCartAccess: a guest must present a valid proof, and a signed-in customer must own the cart. Staff with canManageOrders can read any cart. A checkout link may carry ?cart_proof=. The middleware turns it into the cookie and sends the shopper to the address step. A bare cart ID is never accepted.

Checkout workflow

  1. createActiveCart(regionId) creates a cart in the region for the current country.
  2. Add and change lines (updateActiveCart, updateActiveCartLineItem) and apply discount codes (addDiscountToActiveCart, removeDiscountFromActiveCart).
  3. Set email and addresses with updateActiveCart. Changing them clears the payment collection.
  4. List options with activeCartShippingOptions and choose one with addActiveCartShippingMethod.
  5. List providers with activeCartPaymentProviders(regionId). Then call createActiveCartPaymentSessions and initiatePaymentSession. Only installed providers that are configured in the environment and linked to the cart's region can start a session.
  6. Call completeActiveCart(cartId, paymentSessionId). The server reserves stock and discount usage, checks the provider status, captures if needed, checks amount and currency against the cart, and creates the order with line snapshots. Each step is recorded so a retry resumes instead of charging twice.
  7. Without a paymentSessionId, a signed-in customer with an active business account checks out on account credit. The order is added to the account if it fits the credit limit and uses the account currency.

Limitations

  • The Manual provider (pp_system_default, shown as Cash on Delivery) is refused by completeActiveCart. The storefront still shows a "Place order" button for it, and that order fails.
  • Gift cards cannot be applied. updateActiveCart rejects giftCards, even though the cart UI has gift-card display code.
  • The account checkout-link pages read a bare cartId and try to set the cart's user. Cart access rules reject a cart ID without a proof for anyone who does not own the cart, and updateActiveCart drops user changes. Treat that route as not working. The MCP getCheckoutLink tool builds the same kind of URL.
  • Customers cannot start returns or claims from the storefront. Staff create them in the dashboard.
  • getMyPrivacyData, updatePrivacyPreferences and requestPrivacyAction exist in the API, but no storefront page calls them.

Custom storefronts

You can change the built-in storefront or build another client. Use the same cart proof header and the named cart, checkout and account operations. Do not expose provider credentials or call generic list mutations from the browser.

On this page