E-Commerce

Headless Magento: Integrating Next.js with Adobe Commerce GraphQL for Sub-Second Page Loads

By Laurince QuijanoJuly 9, 20267 min read
Headless Magento: Integrating Next.js with Adobe Commerce GraphQL for Sub-Second Page Loads

Monolithic e-commerce platforms like Adobe Commerce (Magento) are incredibly powerful backend engines. They handle complex inventory, multi-store checkouts, tax tables, and customer segmentations with ease.

However, when it comes to the presentation layer, Magento's traditional XML layout hierarchy and PHP-templated views (like the default Luma theme) are notorious for causing slow load times and low mobile PageSpeed scores. Massive JS payloads, render-blocking CSS, and heavy database lookups block the browser's initial paint.

To solve this, modern e-commerce brands are going headless. By decoupling the presentation layer from the core backend, we can build a blazing-fast Next.js frontend that fetches store data dynamically using Magento's native GraphQL API.

Here is the architecture blueprint and code implementation to build a headless Next.js storefront on top of Adobe Commerce.

---

The Headless Commerce Architecture Blueprint

In a headless configuration, we divide the site into two distinct zones: 1. Frontend (Next.js): A lightweight React application deployed to global CDN edge nodes (like Vercel). It prerenders product catalog pages statically and handles user interactions. 2. Backend (Magento): Runs in a secure, containerized private network, serving exclusively as a headless database engine. It exposes product details, cart state, and customer data via a high-performance GraphQL API.

By decoupling the system, we eliminate Magento's rendering bottlenecks, bringing mobile Largest Contentful Paint (LCP) times down from 4.5 seconds to under 1.2 seconds.

---

Step-by-Step Implementation

1. Fetching Catalog Data via Magento GraphQL First, we write a highly optimized GraphQL query to fetch product catalog parameters based on a specific SKU. By requesting only the exact fields we need (e.g., name, price, images, and description), we minimize database payload sizes:

query GetProductBySku($sku: String!) {
  products(filter: { sku: { eq: $sku } }) {
    items {
      name
      sku
      price_range {
        minimum_price {
          regular_price {
            value
            currency
          }
        }
      }
      image {
        url
        label
      }
      description {
        html
      }
    }
  }
}

2. Constructing the Next.js Server Component In Next.js, we execute this GraphQL request inside a React Server Component. This means the query executes on the server at build time or during request processing, passing raw HTML to the user's browser with zero client-side JavaScript execution required:

const PRODUCT_QUERY = ` query GetProductBySku($sku: String!) { products(filter: { sku: { eq: $sku } }) { items { name sku price_range { minimum_price { regular_price { value currency } } } image { url } } } } `;

async function getProductData(sku: string) { const response = await fetch(GRAPHQL_ENDPOINT, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ query: PRODUCT_QUERY, variables: { sku }, }), // Caches catalog pages for 1 hour, revalidating in the background next: { revalidate: 3600 }, });

const { data } = await response.json(); return data.products.items[0]; }

3. Handling Dynamic Add-to-Cart Actions While catalog details can be statically cached at the CDN edge, customer-specific actions like "Add to Cart" must remain dynamic. We handle this client-side using Magento's createEmptyCart and addProductsToCart GraphQL mutations, storing the generated cart ID inside browser cookies:

// Example Client Component Action
async function handleAddToCart(cartId: string, sku: string, quantity: number) {
  const mutation = `
    mutation AddToCart($cartId: String!, $sku: String!, $quantity: Float!) {
      addProductsToCart(
        cartId: $cartId,
        cartItems: [{ sku: $sku, quantity: $quantity }]
      ) {
        cart {
          total_quantity
        }
      }
    }

const response = await fetch("https://magento-backend.example.com/graphql", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ mutation, variables: { cartId, sku, quantity } }), }); return response.json(); }

---

Why High-Ticket Brands Choose Headless Magento

Migrating to a decoupled, headless Next.js storefront offers three key business advantages: 1. Sub-Second Speed: Loading speeds drop below 1 second, directly raising checkout conversion rates by 15-20%. 2. Deployment Independence: Frontend developers can roll out changes to landing pages and UI components in seconds without running risky, full-stack Magento compilations or cache cleanses. 3. Modern Developer Experience: Developers write clean, modular React components instead of navigating complex Magento layout XML layouts and Knockout.js templates.

By shifting the presentation layer to Next.js and keeping Adobe Commerce as a backend database, e-commerce brands secure a modern, scalable architecture built for speed and high conversions.

Need premium developer consulting?

Let's discuss how we can build API split checkouts, dynamic Next.js interfaces, or speed audits for your business.

Get in Touch