How to Migrate Your Shopify Store to Headless Commerce


Key Takeaways
- Storefront API decouples frontend while Shopify handles checkout
- Next.js or Hydrogen are the strongest framework choices
- Multi-currency needs the @inContext GraphQL directive
- Budget 8–16 weeks and plan for ongoing maintenance costs
- Redirect mapping is critical to preserve SEO rankings
To migrate a Shopify store to headless commerce, decouple your frontend from Shopify's backend using the Storefront API, build a custom frontend with a framework like Next.js or Hydrogen, connect your data layer, and redirect traffic. The process typically takes 8–16 weeks depending on catalog complexity and the number of third-party integrations.
Why Would You Migrate a Shopify Store to Headless Commerce?
Headless commerce separates your storefront's presentation layer from the commerce engine. Shopify continues to handle products, checkout, inventory, and payments, but your frontend — what customers actually see and interact with — runs independently on a framework you control.
The reasons to go headless vary by market and business model, but the most common drivers we see from clients across Asia are:
- Performance in low-bandwidth markets. Static-generated pages and edge-cached content load significantly faster in Southeast Asian markets where mobile connections can be inconsistent. According to Google's Web Vitals research, pages that meet Core Web Vitals thresholds see 24% fewer abandonments.
- Multi-market, multi-language flexibility. A headless frontend gives you full control over locale routing, content structure, and UX patterns that differ across Hong Kong, Taiwan, Singapore, and beyond — without being constrained by Shopify's theme architecture.
- Composable architecture. You can plug in a headless CMS (Contentful, Sanity, Strapi) for editorial content, a separate search provider (Algolia, Typesense), and market-specific payment gateways without modifying the Shopify backend.
- Custom checkout experiences. Shopify Plus merchants can use the Checkout Extensibility API to customize checkout, but headless gives you even more control over pre-checkout flows, bundling UIs, and subscription logic.
According to Shopify's own 2024 Commerce Trends report, merchants using headless architectures reported 30–50% improvements in page load times compared to traditional Liquid themes. That said, headless is not universally the right choice — it adds infrastructure complexity and ongoing maintenance costs. For stores with simple catalogs and no multi-market requirements, a well-optimized Shopify theme may be sufficient.
What Are the Prerequisites Before Starting?
Before writing a single line of code, make sure these foundations are in place:
Shopify Plan Requirements
You need access to the Storefront API, which is available on all Shopify plans. However, for production headless builds, we strongly recommend Shopify Plus because it provides:
- Higher Storefront API rate limits (per Shopify's API documentation, Plus merchants get significantly more generous throttling)
- Access to Checkout Extensibility and Functions
- Multi-currency and multi-language at the platform level
- Dedicated support and a launch engineer
Technical Prerequisites
- Node.js 18+ installed locally
- A Shopify Storefront API access token — generated in your Shopify admin under Settings → Apps and sales channels → Develop apps
- Git and a deployment platform account (Vercel, Netlify, or Cloudflare Pages)
- A headless CMS account if you plan to manage non-commerce content separately (optional but recommended)
- Your current theme's audit — document every custom feature, third-party script, and integration in your existing Liquid theme
API Token Setup
In your Shopify admin:
- Go to Settings → Apps and sales channels → Develop apps
- Click Create an app and name it (e.g.,
headless-storefront) - Under Configuration, select the Storefront API scopes you need. At minimum, enable:
unauthenticated_read_product_listingsunauthenticated_read_product_inventoryunauthenticated_read_customers(if using customer accounts)unauthenticated_write_checkoutsunauthenticated_read_checkoutsunauthenticated_read_content
- Click Install app and copy your Storefront API access token
Store this token securely — it will be used as an environment variable in your frontend application. Never commit it to a public repository.
Ready to Transform Your Ecommerce Operations?
Branch8 specializes in ecommerce platform implementation and AI-powered automation solutions. Contact us today to discuss your ecommerce automation strategy.
Which Frontend Framework Should You Choose?
This is one of the most consequential decisions in the migration. Here are the three most viable options for Shopify headless storefronts in 2025–2026:
Hydrogen + Oxygen (Shopify's Own Stack)
Hydrogen is Shopify's React-based framework built specifically for headless Shopify storefronts. It runs on Oxygen, Shopify's hosting infrastructure.
- Pros: Tight Storefront API integration, built-in cart and checkout utilities, Shopify-managed hosting, SSR with streaming
- Cons: Vendor lock-in to Shopify's hosting (Oxygen), smaller community compared to Next.js, fewer third-party tutorials
- Best for: Teams that want the fastest path to a headless Shopify store and are comfortable with React
Next.js (Vercel)
Next.js 14+ with the App Router is the most popular choice for headless commerce broadly. The @shopify/hydrogen-react package provides React hooks and components you can use outside of Hydrogen.
- Pros: Massive community, flexible deployment (Vercel, Cloudflare, self-hosted), ISR and SSG for performance, extensive plugin library
- Cons: You build more from scratch compared to Hydrogen, need to manage Shopify data fetching patterns yourself
- Best for: Teams with existing Next.js expertise or those who need to integrate multiple backends beyond Shopify
Nuxt 3 (Vue.js)
If your team is Vue-focused, Nuxt 3 is a strong option. There's no official Shopify SDK for Vue, but the Storefront API is GraphQL-based, so any GraphQL client works.
- Pros: Vue's approachability, Nitro server engine for flexible deployment, strong in APAC development communities (particularly popular in Taiwan and Vietnam)
- Cons: No official Shopify component library, more manual integration work
- Best for: Vue-skilled teams willing to build their own Shopify integration layer
When our team migrated a Hong Kong fashion retailer's Shopify Plus store to headless in Q3 2025, we chose Next.js 14 on Vercel because the client also needed to pull editorial content from Sanity CMS and product reviews from Judge.me's API. The migration took 11 weeks from kickoff to launch, with a 3-person frontend team in our Vietnam office and a technical architect in Hong Kong. Post-launch, the client's Largest Contentful Paint (LCP) dropped from 4.2s to 1.1s, and their mobile conversion rate increased by 18% within the first 60 days.
How Do You Set Up the Headless Frontend? (Step-by-Step)
The following steps use Next.js 14 with the App Router. Adjust accordingly if you chose Hydrogen or Nuxt.
Step 1: Initialize the Project
1npx create-next-app@latest my-headless-store --typescript --tailwind --app2cd my-headless-store
Install the Shopify dependencies:
1npm install @shopify/hydrogen-react graphql graphql-request
Step 2: Configure Environment Variables
Create a .env.local file in your project root:
1SHOPIFY_STORE_DOMAIN=your-store.myshopify.com2SHOPIFY_STOREFRONT_API_TOKEN=your_storefront_api_token_here3SHOPIFY_STOREFRONT_API_VERSION=2025-01
The API version should match Shopify's latest stable release. As of early 2026, 2025-01 or 2025-04 are current. Check Shopify's API versioning documentation for the latest.
Step 3: Create the Shopify Client
Create a utility file at lib/shopify.ts:
1import { GraphQLClient } from 'graphql-request';23const domain = process.env.SHOPIFY_STORE_DOMAIN!;4const token = process.env.SHOPIFY_STOREFRONT_API_TOKEN!;5const apiVersion = process.env.SHOPIFY_STOREFRONT_API_VERSION!;67const endpoint = `https://${domain}/api/${apiVersion}/graphql.json`;89export const shopifyClient = new GraphQLClient(endpoint, {10 headers: {11 'X-Shopify-Storefront-Access-Token': token,12 'Content-Type': 'application/json',13 },14});1516export async function shopifyFetch<T>(query: string, variables?: Record<string, unknown>): Promise<T> {17 try {18 const data = await shopifyClient.request<T>(query, variables);19 return data;20 } catch (error) {21 console.error('Shopify API Error:', error);22 throw error;23 }24}
Step 4: Fetch Products
Create a query file at lib/queries/products.ts:
1import { gql } from 'graphql-request';23export const GET_PRODUCTS = gql`4 query GetProducts($first: Int!) {5 products(first: $first) {6 edges {7 node {8 id9 title10 handle11 description12 priceRange {13 minVariantPrice {14 amount15 currencyCode16 }17 }18 images(first: 1) {19 edges {20 node {21 url22 altText23 width24 height25 }26 }27 }28 }29 }30 }31 }32`;3334export const GET_PRODUCT_BY_HANDLE = gql`35 query GetProductByHandle($handle: String!) {36 productByHandle(handle: $handle) {37 id38 title39 description40 variants(first: 25) {41 edges {42 node {43 id44 title45 priceV2 {46 amount47 currencyCode48 }49 availableForSale50 }51 }52 }53 images(first: 10) {54 edges {55 node {56 url57 altText58 width59 height60 }61 }62 }63 }64 }65`;
Step 5: Build the Product Listing Page
Create app/products/page.tsx:
1import { shopifyFetch } from '@/lib/shopify';2import { GET_PRODUCTS } from '@/lib/queries/products';3import Link from 'next/link';45interface ProductsResponse {6 products: {7 edges: Array<{8 node: {9 id: string;10 title: string;11 handle: string;12 description: string;13 priceRange: {14 minVariantPrice: {15 amount: string;16 currencyCode: string;17 };18 };19 images: {20 edges: Array<{21 node: {22 url: string;23 altText: string | null;24 };25 }>;26 };27 };28 }>;29 };30}3132export default async function ProductsPage() {33 const data = await shopifyFetch<ProductsResponse>(GET_PRODUCTS, { first: 20 });3435 return (36 <div className="grid grid-cols-2 md:grid-cols-4 gap-6 p-8">37 {data.products.edges.map(({ node }) => (38 <Link key={node.id} href={`/products/${node.handle}`}>39 <div className="group cursor-pointer">40 {node.images.edges[0] && (41 <img42 src={node.images.edges[0].node.url}43 alt={node.images.edges[0].node.altText || node.title}44 className="w-full aspect-square object-cover"45 />46 )}47 <h2 className="mt-2 text-sm font-medium">{node.title}</h2>48 <p className="text-sm text-gray-600">49 {node.priceRange.minVariantPrice.currencyCode}{' '}50 {parseFloat(node.priceRange.minVariantPrice.amount).toFixed(2)}51 </p>52 </div>53 </Link>54 ))}55 </div>56 );57}
Expected output: Run npm run dev, navigate to http://localhost:3000/products, and you should see a grid of your Shopify products with images, titles, and prices.
Step 6: Implement the Cart with Storefront API
The Storefront API uses a Cart object (which replaced the older Checkout object). Create lib/queries/cart.ts:
1import { gql } from 'graphql-request';23export const CREATE_CART = gql`4 mutation CreateCart($input: CartInput!) {5 cartCreate(input: $input) {6 cart {7 id8 checkoutUrl9 lines(first: 10) {10 edges {11 node {12 id13 quantity14 merchandise {15 ... on ProductVariant {16 id17 title18 priceV2 {19 amount20 currencyCode21 }22 }23 }24 }25 }26 }27 }28 userErrors {29 field30 message31 }32 }33 }34`;3536export const ADD_TO_CART = gql`37 mutation AddToCart($cartId: ID!, $lines: [CartLineInput!]!) {38 cartLinesAdd(cartId: $cartId, lines: $lines) {39 cart {40 id41 checkoutUrl42 lines(first: 50) {43 edges {44 node {45 id46 quantity47 merchandise {48 ... on ProductVariant {49 id50 title51 }52 }53 }54 }55 }56 }57 userErrors {58 field59 message60 }61 }62 }63`;
The checkoutUrl returned by the Cart API directs customers to Shopify's hosted checkout. On Shopify Plus, you can customize this checkout using Checkout Extensibility. For non-Plus stores, the hosted checkout is your only option — but it handles payments, taxes, and shipping reliably across all markets.
Ready to Transform Your Ecommerce Operations?
Branch8 specializes in ecommerce platform implementation and AI-powered automation solutions. Contact us today to discuss your ecommerce automation strategy.
How Do You Handle Multi-Currency and Multi-Language for Asian Markets?
This is where headless becomes particularly valuable for cross-border APAC operations. Shopify Markets (available on Plus) provides the backend infrastructure for multi-currency and localized pricing, but your headless frontend needs to handle locale detection and routing.
Add a @shopify/hydrogen-react context wrapper for international pricing. In your Storefront API queries, include the @inContext directive:
1query GetProducts($first: Int!, $country: CountryCode!, $language: LanguageCode!)2 @inContext(country: $country, language: $language) {3 products(first: $first) {4 edges {5 node {6 title7 priceRange {8 minVariantPrice {9 amount10 currencyCode11 }12 }13 }14 }15 }16}
Pass country: "HK" and language: "ZH" for Hong Kong, or country: "SG" and language: "EN" for Singapore. This returns localized prices in the correct currency automatically, assuming you've configured Shopify Markets in your admin.
According to Shopify's Markets documentation, the @inContext directive supports all countries and languages that you've enabled in your Shopify Markets settings. For our Hong Kong fashion retailer, we configured five markets (HK, TW, SG, MY, PH) and used Next.js middleware to detect the user's country via Vercel's x-vercel-ip-country header, routing them to the appropriate locale prefix.
How Do You Handle Redirects and SEO During Migration?
This step is critical and often underestimated. A poorly handled migration can destroy your organic search traffic.
URL Structure Mapping
Shopify's default URL structure uses patterns like:
/products/product-handle/collections/collection-handle/pages/page-handle/blogs/news/article-handle
Your headless frontend doesn't have to match these exactly, but if you change any URLs, you must set up 301 redirects. We recommend keeping the same URL structure to minimize redirect chains.
Redirect Configuration in Next.js
In your next.config.js:
1module.exports = {2 async redirects() {3 return [4 // Example: if you changed collection URLs5 {6 source: '/collections/:handle',7 destination: '/shop/:handle',8 permanent: true,9 },10 ];11 },12};
Metadata and Structured Data
Use Next.js 14's Metadata API to generate dynamic SEO tags from Shopify product data:
1// app/products/[handle]/page.tsx2import type { Metadata } from 'next';34export async function generateMetadata({ params }: { params: { handle: string } }): Promise<Metadata> {5 const product = await getProductByHandle(params.handle);6 return {7 title: product.seo?.title || product.title,8 description: product.seo?.description || product.description?.substring(0, 155),9 openGraph: {10 images: [product.images.edges[0]?.node.url],11 },12 };13}
Add JSON-LD structured data for products to maintain rich snippets in search results. According to Google's Search Central documentation, Product structured data should include name, image, description, offers with price and priceCurrency, and availability.
Ready to Transform Your Ecommerce Operations?
Branch8 specializes in ecommerce platform implementation and AI-powered automation solutions. Contact us today to discuss your ecommerce automation strategy.
How Do You Deploy and Go Live?
Deployment Options
- Vercel — The most straightforward option for Next.js. Push to GitHub, connect to Vercel, and deployments happen automatically. Edge functions run across global PoPs including Hong Kong, Singapore, and Tokyo.
- Cloudflare Pages — Strong option if you're already using Cloudflare for DNS/CDN. Their Asia network coverage is extensive, with data centers in over 30 Asian cities according to Cloudflare's network page.
- Oxygen — If you chose Hydrogen, Shopify's Oxygen hosting is the default deployment target.
Go-Live Checklist
- Verify all Storefront API queries return correct data in production environment variables
- Test checkout flow end-to-end — add to cart, proceed to Shopify checkout, complete a test purchase
- Validate redirects — use a tool like Screaming Frog to crawl your old sitemap and confirm every URL either resolves or redirects
- Submit updated sitemap to Google Search Console
- Test multi-currency — use a VPN to verify pricing displays correctly for each target market
- Performance audit — run Lighthouse and Web Vitals checks from multiple Asian locations using WebPageTest's global test agents
- Monitor API rate limits — Shopify's Storefront API uses a cost-based throttling system. According to Shopify's API rate limits documentation, each app gets a bucket of 1000 cost points that refills at 100 points per second for standard plans
DNS Cutover
Point your domain to your new hosting provider. If you're on Vercel:
- Add your domain in the Vercel dashboard
- Update your DNS A/CNAME records
- Vercel handles SSL provisioning automatically
Keep your Shopify store active — it still powers your checkout, admin, and backend. You're only moving where the frontend is served from.
What Are Common Pitfalls and How Do You Troubleshoot Them?
API Rate Limiting
Symptom: Intermittent 429 errors or slow responses during traffic spikes.
Fix: Implement request caching aggressively. Use Next.js ISR (Incremental Static Regeneration) or fetch with next: { revalidate: 60 } to cache Storefront API responses. For product pages, a 60-second revalidation window means you hit the API once per minute per page, not once per visitor.
Cart State Persistence
Symptom: Users lose their cart when navigating between pages or returning to the site.
Fix: Store the cartId in a cookie (not localStorage) so it persists across sessions and works with server-side rendering. Use js-cookie or Next.js server actions to manage this.
Checkout Domain Mismatch
Symptom: Customers see a jarring transition from your custom domain to checkout.shopify.com.
Fix: On Shopify Plus, you can configure a custom checkout domain. Without Plus, this redirect is unavoidable but can be smoothed with consistent branding in Shopify's checkout customization settings.
Image Optimization
Symptom: Product images load slowly despite fast page rendering.
Fix: Shopify's CDN supports dynamic image resizing via URL parameters. Append _400x400 or use the width and height parameters in the Storefront API image URLs. Combine with Next.js <Image> component for automatic format negotiation and lazy loading.
1// Shopify CDN image resizing2const optimizedUrl = `${originalUrl}&width=800&height=800`;
Ready to Transform Your Ecommerce Operations?
Branch8 specializes in ecommerce platform implementation and AI-powered automation solutions. Contact us today to discuss your ecommerce automation strategy.
What Does This Cost and How Long Does It Take?
Timelines and budgets vary significantly, but here are realistic ranges based on our project history across APAC:
- Simple catalog (under 500 SKUs, single market): 6–10 weeks, USD $25,000–$50,000
- Mid-complexity (500–5,000 SKUs, 2–3 markets, headless CMS integration): 10–16 weeks, USD $50,000–$120,000
- Enterprise (5,000+ SKUs, 5+ markets, custom checkout, multiple integrations): 16–24 weeks, USD $120,000–$300,000+
These ranges include discovery, design, development, QA, and launch support. According to Statista's 2024 global e-commerce data, APAC represents over 60% of global e-commerce sales, which makes the investment in a performant, localized headless storefront particularly justifiable for brands targeting this region.
One honest trade-off: ongoing maintenance costs for a headless store are higher than a standard Shopify theme. You're responsible for frontend hosting, build pipelines, and keeping your API integration current with Shopify's quarterly API version releases. Budget an additional 15–20% of the initial build cost annually for maintenance and updates.
If you're considering a headless migration for your Shopify store — especially one serving multiple Asian markets — Branch8's engineering teams across Hong Kong, Vietnam, and Singapore have delivered headless builds on Next.js, Hydrogen, and Nuxt for retail, fashion, and D2C brands. Get in touch with our e-commerce team to discuss your migration scope and timeline.
Sources
FAQ
No, the Storefront API is available on all Shopify plans. However, Shopify Plus provides higher API rate limits, Checkout Extensibility for customizing the checkout experience, and multi-currency through Shopify Markets — all of which are important for production headless stores serving multiple markets.