Skip to content
Saleor
Esc
↑↓navigate↵open⌘Jpreview
On this page

Storefront integration guidelines

This chapter contains guidelines for integrating a storefront with Saleor.

Images

  • Serve thumbnails straight from Saleor’s CDN. They are already resized and converted. Running them through an image optimizer such as Next.js next/image on Vercel or Netlify processes them a second time, and those platforms bill per transformation.
  • Request several sizes in one query and render <img srcset>. Alias the field, e.g. thumbnail256: thumbnail(size: 256, format: WEBP), and let the browser pick. See SaleorImage for an implementation.
  • Request each size from the API. Don’t change the size in a returned URL: a direct media URL with a different size returns 404.
  • Use your framework’s or host’s image optimizer only for images Saleor doesn’t resize, such as files bundled with your app.

Product availability

  • Check which stock mode the shop uses. Query shop { useLegacyShippingZoneStockAvailability }. In legacy mode, stock counts only in warehouses that are assigned to the channel and to one of its shipping zones. Otherwise, a warehouse assigned to the channel is enough. See Stock.
  • Don’t treat isAvailable as a promise of delivery. Outside legacy mode, a product can be added to the cart and still have no shipping method for the customer’s address. Handle that case in checkout.
  • A product is purchasable in a channel only when it is published and available for purchase there, the variant has a price in that channel, and stock is reachable as described above.

Caching

  • Cache catalog data, never cart or checkout data. Product, category and menu queries can be cached and refreshed with webhooks such as PRODUCT_UPDATED or MENU_UPDATED. Always fetch the cart and checkout live.
  • A cached price is safe to show. Saleor recalculates prices when lines are added to a checkout and when it’s completed, so a customer can’t pay a stale price.
  • Keep per-customer data out of the shared cache. If one customer’s cart or session change clears a shared cache entry, every visitor triggers a re-render.
  • Don’t cache responses that contain errors. Saleor can return partial data alongside errors, e.g. a product without a price. Cached, it stays broken until the cache expires.

Orders

  • Treat the order ID like a password. Anyone who has it can read the order with order(id:), including the address and email, without signing in. Keep it out of analytics, logs and third-party scripts. On a public order status page, show the address and email only after the customer signs in or confirms the order’s email. See Orders.

Content

  • Store storefront copy in Models. Pages are not channel-scoped and page slugs are unique across the shop, so encode per-channel copy in the slug (e.g. homepage-eu) and fall back to a shared page.

Translations

  • Fall back to the base field when a translation is missing. translation(languageCode:) returns null for untranslated content instead of the default-language text. See Translations.
  • Keep language and channel separate. One channel can serve several languages, so a language alone doesn’t determine prices or stock.

Last updated on November 12, 2026

Was this page helpful?