A complete headless commerce storefront: Next.js renders the shop, the Shopify Storefront API supplies the catalog, and the cart is backed by real Shopify cart mutations. No Liquid, no theme — just a GraphQL API and a front end.
Runs against mock.shop, Shopify's public demo Storefront API, so the whole project works with zero credentials, zero backend, and zero environment variables — clone, install, run.
- Headless architecture — the storefront is a standalone Next.js app consuming the Shopify Storefront GraphQL API. Swapping mock.shop for a real store is a one-file change (see below).
- Server-rendered catalog with ISR — home, collection, and product pages are React Server Components fetching GraphQL with
next: { revalidate: 3600 }; the home page is statically prerendered. - Variant-aware product pages — multi-option products (Size × Color) with a variant matcher: selecting options resolves the exact variant, updating price, availability, and the per-variant hero image. Gallery with thumbnails.
- A real cart, not local state — add/update/remove call Shopify's
cartCreate,cartLinesAdd,cartLinesUpdate, andcartLinesRemovemutations from the browser. The cart ID persists inlocalStorage, so the cart survives reloads, and checkout hands off to Shopify's hosted checkout URL. - Pure, tested core — money formatting, variant matching, selection defaults, quantity clamping, and cart normalization live in
src/lib/catalog.tswith a dependency-free test script (17 assertions).
| Collection | Product + live cart |
|---|---|
![]() |
![]() |
- Next.js 16 (App Router, React Server Components, Turbopack)
- Shopify Storefront API via mock.shop
- Tailwind CSS v4
- TypeScript, strict
Browser ──► Next.js (RSC, ISR) ──► Storefront API (catalog reads, cached 1h)
Browser ─────────────────────────► Storefront API (cart mutations, CORS)
Checkout ────────────────────────► Shopify hosted checkout (cart.checkoutUrl)
src/lib/shopify.ts— GraphQL client (server + browser variants) and all queries/mutations as typed documents with shared fragments.src/lib/catalog.ts— pure logic:formatMoney,matchVariant,defaultSelection,clampQuantity,normalizeCart.src/components/CartContext.tsx— client cart state; hydrates from a persisted cart ID, runs the four cart mutations, opens the drawer on add.src/app/{page,collections/[handle],products/[handle]}— server components for catalog pages.
npm install
npm run devNo configuration needed. Tests, lint, and typecheck:
npm test # pure catalog logic (17 assertions)
npm run lint
npx tsc --noEmitSet NEXT_PUBLIC_SHOPIFY_API_URL to your store's Storefront API endpoint (https://your-store.myshopify.com/api/2025-01/graphql.json) and add your public Storefront access token as an X-Shopify-Storefront-Access-Token header in src/lib/shopify.ts. Everything else — queries, cart, checkout handoff — is the standard Storefront API surface and works unchanged.
MIT


