Headless Shopify Integration
Relevant source files
The following files were used as context for generating this wiki page:
The Headless Shopify Integration is the core commerce engine of the platform, utilizing the Shopify Storefront API for customer-facing operations (catalog, cart, checkout) and the Shopify Admin API for back-office management. The system is designed to be multi-tenant, where a single deployment serves multiple shops by resolving tenants at the edge via hostname and passing explicit { shop, locale } contexts to every downstream Shopify call.
Sources: README.md:16-18, CONTEXT.md:7-11, apps/storefront/README.md:9-11
Architecture and Tenancy
The integration follows a "multi-tenant by hostname" architecture. When a request arrives, the middleware resolves the hostname to a specific Shop record. This record contains the necessary Commerce provider configuration, specifically the shopify provider type and its associated Provider tokens.
Multi-Tenant Flow
Every Shopify interaction is strictly tenant-scoped. The system prevents implicit context; data-fetching helpers must receive the shop and locale explicitly to construct the appropriate API client.
The diagram shows how a request is resolved to a tenant before any Shopify calls are made.
Sources: CONTEXT.md:144-147, apps/storefront/README.md:27-35, CLAUDE.md:68-75
API Clients and Data Fetching
The platform provides two primary ways to interact with Shopify, governed by the ShopifyApiOptions shape.
Shopify API Client Types
| Client Type | Implementation | Primary Use Case |
|---|---|---|
ShopifyApolloApiClient | Apollo + Hydrogen | Default client for standard storefront queries. |
ShopifyApiClient | Fetch-based stub | Used for cache-controlled paths requiring explicit Next.js fetchOptions. |
Sources: CONTEXT.md:290-296, apps/storefront/README.md:52-57
Automatic Context Injection
The system uses a custom Apollo transform from @nordcom/commerce-shopify-graphql to automatically inject the @inContext(country, language) directive into GraphQL operations. Source operations must not pre-declare these variables to avoid DuplicateContextDirectiveError.
Sources: apps/storefront/README.md:59-64
Caching and Invalidation
Caching is partitioned by Cache Namespace (e.g., shopify) and is strictly Tenant-scoped and Locale-qualified.
Cache Tag Structure
Cache tags are built using the buildCacheTagArray(shop, locale, [...extra]) utility. This ensures that revalidating data for one tenant or locale does not affect others.
| Tag Level | Format | Description |
|---|---|---|
| Global | shopify | Broadest Shopify cache namespace. |
| Tenant | shopify.<shopId> | All Shopify data for a specific shop. |
| Entity | shopify.<shopId>.product.<handle> | Surgical tag for a specific product. |
Sources: apps/storefront/README.md:69-75, CONTEXT.md:46-59
Webhook Processing
The /[domain]/api/revalidate endpoint handles incoming Shopify webhooks. It performs HMAC verification via X-Shopify-Hmac-SHA256 and maps topics (like products/update) to the specific cache tags for invalidation.
The flow demonstrates the mapping of Shopify webhook topics to surgical cache tags.
Sources: apps/storefront/README.md:82-89, packages/tagtree/shopify/README.md:37-45
Cart System
The cart is managed via the @nordcom/cart-shopify package, which acts as a Cart Adapter for the Cart Kernel.
Components of the Cart Integration
- Cart Adapter: Implements Shopify-specific network calls and data normalization.
- Transport: A host-supplied function (e.g.,
ShopifyTransport) that performs the actual GraphQL calls. - Buyer Identity: Carries Shopify-specific session tokens like
customerAccessToken.
Sources: CONTEXT.md:195-212, packages/cart/shopify/package.json
CMS and Block Loaders
While the CMS (@nordcom/commerce-cms) is Shopify-agnostic, certain Blocks (like collection or overview) require Shopify data.
Block Loader Architecture
To maintain an architectural firewall, the CMS defines data needs as a contract. The Storefront supplies Block Loaders at the rendering boundary, which use the Shopify API client to fetch the required product or collection data.
Sources: CONTEXT.md:92-95, packages/cms/README.md:52-65
Summary
The Headless Shopify Integration provides a robust, multi-tenant framework for commerce. By strictly enforcing tenant context through explicit shop/locale passing and utilizing surgical cache invalidation via webhooks, the system achieves high performance and isolation across multiple storefronts served by a single deployment.
Sources: README.md:92-101, CONTEXT.md:23-26