Setting Up Next.js with Shopify for E-commerce

Integrating Shopify with Next.js allows you to build a high-performance e-commerce site with the flexibility of React and the power of Shopify's e-commerce platform.

Next.jsFramework
ShopifyE-Commerce

Tom McCulloch

Read Time: 3 min

Integrating Shopify with Next.js allows you to build a high-performance e-commerce site with the flexibility of React and the power of Shopify's e-commerce platform. This guide will walk you through setting up a Next.js application with Shopify using GraphQL for data fetching.

Prerequisites

  • Basic knowledge of JavaScript and React
  • Node.js installed on your machine
  • Shopify store set up

Set Up Your Next.js Project

First, create a new Next.js project if you haven't already:

npx create-next-app@latest my-shopify-store
cd my-shopify-store

Install Necessary Packages

Install the required packages, including Apollo Client for GraphQL:

npm install @apollo/client graphql @headlessui/react @heroicons/react

Set Up Apollo Client

Create a new file lib/apollo-client.js to configure Apollo Client:

// lib/apollo-client.js
import { ApolloClient, InMemoryCache } from '@apollo/client';

const client = new ApolloClient({
  uri: `https://${process.env.NEXT_PUBLIC_SHOPIFY_STORE_DOMAIN}/api/2023-04/graphql.json`,
  headers: {
    'X-Shopify-Storefront-Access-Token': process.env.NEXT_PUBLIC_SHOPIFY_STOREFRONT_ACCESS_TOKEN,
    'Content-Type': 'application/json',
  },
  cache: new InMemoryCache(),
});

export default client;

Fetch Products from Shopify

Create a new file lib/shopify.js to fetch products from Shopify using GraphQL:

// lib/shopify.js
import { gql } from '@apollo/client';
import client from './apollo-client';

export async function getAllProducts() {
  const query = gql`
    query {
      products(first: 25) {
        edges {
          node {
            id
            title
            handle
            description
            images(first: 1) {
              edges {
                node {
                  url
                  altText
                }
              }
            }
            variants(first: 1) {
              edges {
                node {
                  price {
                    amount
                  }
                }
              }
            }
          }
        }
      }
    }
  `;

  const { data } = await client.query({ query });
  return data.products.edges;
}

export async function getProductByHandle(handle) {
  const query = gql`
    query getProduct($handle: String!) {
      productByHandle(handle: $handle) {
        id
        title
        description
        images(first: 5) {
          edges {
            node {
              url
              altText
            }
          }
        }
        variants(first: 5) {
          edges {
            node {
              price {
                amount
              }
            }
          }
        }
      }
    }
  `;

  const { data } = await client.query({
    query,
    variables: { handle },
  });
  return data.productByHandle;
}

Create Dynamic Routes for Products

Set up dynamic routing in Next.js to handle individual product pages.

'app/products/[handle]/page.js'

// app/products/[handle]/page.js
import { getProductByHandle, getAllProducts } from '../../lib/shopify';

export default async function ProductPage({ params }) {
  const product = await getProductByHandle(params.handle);

  return (
    <div className="bg-white">
      <h1 className="text-2xl font-bold tracking-tight text-gray-900 sm:text-3xl">{product.title}</h1>
      <img src={product.images.edges[0].node.originalSrc} alt={product.images.edges[0].node.altText} />
      <p>{product.description}</p>
      <p className="text-3xl tracking-tight text-gray-900">${product.variants.edges[0].node.priceV2.amount}</p>
    </div>
  );
}

export async function generateStaticParams() {
  const products = await getAllProducts();

  return products.map((product) => ({
    handle: product.node.handle,
  }));
}

Fetch and Display Products on Home Page

app/page.js

// app/page.js
import { getAllProducts } from './lib/shopify';
import Link from 'next/link';

export default async function Home() {
  const products = await getAllProducts();

  return (
    <div className="container mx-auto py-12">
      <h1 className="text-4xl font-bold mb-8">Products</h1>
      <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
        {products.map(product => (
          <div key={product.node.id} className="border p-4 rounded-lg">
            <img src={product.node.images.edges[0].node.originalSrc} alt={product.node.images.edges[0].node.altText} className="w-full h-64 object-cover mb-4"/>
            <h2 className="text-2xl font-bold">{product.node.title}</h2>
            <p>{product.node.description}</p>
            <p className="mt-2">${product.node.variants.edges[0].node.priceV2.amount}</p>
            <Link href={`/products/${product.node.handle}`}>
              <a className="text-blue-500 hover:text-blue-700">View Product</a>
            </Link>
          </div>
        ))}
      </div>
    </div>
  );
}

Conclusion

By following these steps, you have set up a Next.js 14 application with Shopify integration, using Apollo Client to fetch product data via GraphQL. You have also created dynamic routes for individual product pages and displayed a list of products on the home page. This setup provides a solid foundation for building a powerful and flexible e-commerce site.

Feel free to expand this basic setup by adding more features, styles, and customisations to suit your needs. Happy coding!