Demo store on Shopify’s Storefront API. Nothing here ships. How it’s built
Sahel.

Build notes

A headless Shopify store, end to end.

Shopify keeps doing what it’s best at: products, inventory, cart and checkout. The storefront is a Next.js app with full control over design, speed and language. This page explains how the pieces fit together.

01

Shopper

Browses, picks a variant, adds to bag.

02

Next.js on Vercel

Server Components render pages. Server Actions change the cart.

03

Storefront API

GraphQL for products, collections, search and the Cart API.

04

Checkout

Validated on the server; production hands payment to Shopify Checkout.

01

Catalog: server-rendered, cached GraphQL

Every product, collection and search page is a React Server Component that queries the Storefront API directly. No client-side data fetching, no API keys in the browser. Catalog responses are cached and revalidated every 15 minutes, so pages stay fast without going stale.

const res = await fetch(ENDPOINT, {
  method: 'POST',
  headers: { 'X-Shopify-Storefront-Access-Token': TOKEN },
  body: JSON.stringify({ query, variables }),
  next: { revalidate: 900 },   // catalog: cached
  // cache: 'no-store'         // cart: never cached
});

02

Cart: a real Shopify cart through Server Actions

Add to bag, quantity changes and removals call Server Actions that run cartCreate, cartLinesAdd, cartLinesUpdate and cartLinesRemove. The cart ID lives in an httpOnly cookie, so it survives reloads and never touches client JavaScript.

export async function addToCart(merchandiseId: string) {
  'use server';
  const existing = await readCart();
  const line = { merchandiseId, quantity: 1 };
  const cart = existing
    ? await addCartLines(existing.id, [line])
    : await createCart([line]);
  await setCartCookie(cart);
  return cart;
}

03

A checkout built for MENA shoppers

One page: contact, delivery, shipping and payment, with a live order summary. Egyptian addresses use a governorate picker and phone numbers are validated per country. Payment offers cash on delivery and InstaPay where they make sense, alongside cards. Validation runs on the server, and placing the order writes the country, shipping and payment choices onto the Shopify cart with cartBuyerIdentityUpdate and cartAttributesUpdate. In production the card step hands off to the cart’s checkoutUrl on Shopify Checkout; in this demo nothing is charged and personal details never leave the site.

const [state, formAction, pending] = useActionState(placeOrder, {});

// server
await updateBuyerCountry(cart.id, country);
await updateCartAttributes(cart.id, [
  { key: 'Shipping method', value: shipping },
  { key: 'Payment method', value: payment },
]);
redirect('/checkout/thank-you');

04

Variants that behave

Size and colour pickers work out availability from the variant matrix, cross out combinations that can’t be bought, and fall back to the closest real variant when a shopper picks a value that doesn’t exist with their current selection. The choice is mirrored into the URL (?Color=Ocean&Size=Large), so a shared link opens the same variant.

05

Search that answers while you type

Press “/” anywhere. The overlay debounces input and calls a cached route handler backed by predictiveSearch; Enter opens the full results page backed by the search query.

06

English and Arabic from one codebase

The locale is a cookie. The root layout sets <html lang dir>, layout uses logical properties (start/end instead of left/right), the cart drawer slides in from the correct side, prices format with Arabic numerals, and every Storefront query passes @inContext(language). With a real store and Shopify Translate & Adapt, product content comes back in Arabic too.

07

Images straight from Shopify’s CDN

A custom next/image loader asks Shopify’s CDN for the exact width each breakpoint needs, so there’s no second image optimizer in the path.

08

Point it at your store

The demo runs on Shopify’s public mock.shop catalog. Two environment variables switch it to a real store; nothing else in the code changes.

SHOPIFY_STOREFRONT_API_URL=https://your-store.myshopify.com/api/2025-07/graphql.json
SHOPIFY_STOREFRONT_ACCESS_TOKEN=<public Storefront API token>

Want a storefront like this for your Shopify store?

I build custom Shopify apps, checkout extensions and headless storefronts in English and Arabic.