All guides
Apps & Extensions

Shopify Headless Commerce with Next.js: Architecture and Trade-offs

When headless Shopify makes sense, when it doesn't, and how to architect a Next.js + Storefront API setup that performs well in production.

Published
28 June 2026
Reading time
13 min read
In this guide
  1. 01What headless Shopify actually means
  2. 02When headless is worth it
  3. 03The Storefront API
  4. 04Next.js architecture for headless Shopify
  5. 05Cart management
  6. 06Search and filtering
  7. 07Internationalisation with Shopify Markets

What headless Shopify actually means

Headless Shopify means decoupling the storefront (the UI) from Shopify's commerce backend. Instead of using Shopify's Liquid templating engine to render pages, you build a separate frontend (typically Next.js) that fetches data from Shopify via the Storefront API and renders it independently.

Shopify still handles: cart, checkout, payments, orders, products, customers, and inventory. Your Next.js app handles: page rendering, routing, UI components, search, and any custom frontend logic.

The checkout still runs on Shopify's infrastructure — you redirect to Shopify's hosted checkout at the end of the cart flow. True headless checkout (custom checkout UI) requires Checkout Extensibility, which has constraints.

When headless is worth it

Headless makes sense when: - You need performance that Shopify's Liquid rendering can't achieve (e.g. complex product configurators, real-time personalisation) - You're consolidating multiple Shopify stores into one Next.js frontend - You have an existing Next.js or React frontend that needs commerce added - You need content from multiple sources (Shopify + a headless CMS like Contentful or Sanity) rendered together - You need offline-capable or app-like experiences (PWA)

Headless is not worth it when you're trying to improve PageSpeed scores (a well-optimised Liquid theme performs comparably), your team doesn't have strong React/Next.js experience, or you're adding complexity without a specific technical requirement that Liquid can't meet.

The Storefront API

The Storefront API is Shopify's public-facing GraphQL API — authenticated with a public access token (not the admin API key). It's rate-limited separately from the Admin API and is safe to call from the browser.

Key operations via the Storefront API: - Query products, collections, and variants (including metafields marked as storefront-accessible) - Create and manage carts (cartCreate, cartLinesAdd, cartBuyerIdentityUpdate) - Start checkout (redirect to Shopify's checkout using the cart's checkoutUrl) - Query customer accounts and order history (with customer access tokens) - Query selling plan groups for subscription products - Query shop information, markets, and localisation

The Storefront API does not expose orders in detail — for order management, you need the Admin API.

Next.js architecture for headless Shopify

The recommended architecture uses Next.js App Router with Server Components for data fetching and Client Components only for interactive elements (add-to-cart, cart drawer, search).

Page structure: - /products/[handle] — Server Component fetches product via Storefront API, renders static product data, Client Component handles variant selection and add-to-cart - /collections/[handle] — Server Component fetches collection + products, implements ISR (revalidate: 60) so pages rebuild periodically - /cart — Client Component manages cart state via React context or Zustand, syncs with Storefront API - /search — Client Component for real-time search (Algolia, Shopify Predictive Search API, or Typesense)

Use generateStaticParams to pre-render product and collection pages at build time. Set revalidate on collection pages to pick up new products without a full rebuild.

Cart management

Shopify's cart is server-side (stored in Shopify, not in localStorage). You interact with it via the Storefront API cartCreate and cartLinesAdd mutations. Store the cart ID in a cookie so it persists across sessions.

For a good user experience, optimistically update the cart UI before the API call completes, then sync to the server in the background. Use React's useOptimistic hook or a local cart state that reconciles with the server response.

For authenticated users, update the cart buyer identity with the customer's access token — this ensures prices, discounts, and shipping estimates reflect the logged-in customer's context (including B2B pricing if applicable).

Search and filtering

Shopify's native search is basic — it covers product title, description, and tags. For faceted filtering (by price range, attributes, availability) you have two options:

**Shopify's built-in collection filtering** — works on Liquid themes via the search.liquid template. Headless requires custom implementation using the filter API in the Storefront API.

**Third-party search** — Algolia, Typesense, or Elastic. Index Shopify products via webhook sync (product updates push to the search index). The search UI in Next.js queries the search provider directly. This is significantly faster and more flexible, but adds infrastructure cost and complexity.

For most headless projects, starting with Shopify's native collection filtering and adding Algolia when you hit its limits is the right progression.

Internationalisation with Shopify Markets

Shopify Markets integrates with headless via the Storefront API. Pass a country code in the @inContext directive to get market-specific pricing, language, and availability:

```graphql query ProductQuery @inContext(country: DE, language: DE) { product(handle: "example-product") { priceRange { minVariantPrice { amount currencyCode } } } } ```

Detect the buyer's market from their Accept-Language header or IP geolocation in Next.js middleware. Store the selected market in a cookie and pass it to all Storefront API queries.

For subdomain routing (de.yourstore.com → German market), Next.js middleware matches the hostname and sets the market context. For subfolder routing (/de/), use Next.js's built-in i18n routing with the Storefront API market context.

Need help implementing this?

I build what I write about. If you need this implemented on your Shopify store, get in touch.

Discuss your project

Ready to build this on your store?
Let's scope it.

I reply personally within 24 hours.