Shopify

We’re opening up a world where fans feel a meaningful connection to their brands, and where NFTs just increasingly become part of how we buy and sell online. An example is Shopify, which has made it possible for eligible sellers to sell NFTs (non-fungible tokens) via its platform, which opens up a whole new world for e-commerce merchants. By making it possible for merchants to sell NFTs directly through their Shopify storefronts, we're seeing a lot of opportunities to blend Shopify into our app.

Hydrogen Template

A place where LTL/GVO/DDA official merchandise lives. All items are tokenized, meaning that you can buy an NFT that gives you the right to claim an item. Since all items are tokenized, they are limited and require on-chain transactions. LTL will add a non-fungible token (NFT) component to its monthly GVO & DDA Collection. On the first Friday of every month, LTL might make a very limited edition item available for purchase in selected markets for 33 hours. There are often only 300 editions available on a first-come, first-served basis. And the piece is delivered in a custom package straight to the purchaser’s door. The purchase will be unlocked by the LTL Founders Pass NFT.

Next JS Example

npx create-next-app -e with-tailwindcss build-next-shop
cd build-next-shop

Navigate to the Apps tab in your store and hit the "Manage private apps" link at the bottom. Accept the terms and conditions, name your private app "Next.js Connection" and enter your email address. Then scroll down and check "Allow this app to access your storefront data using using the Storefront API".

Create .env.local file in the root folder of your Next.js app and add these variables:

SHOPIFY_STOREFRONT_ACCESSTOKEN='storefront api access token'
SHOPIFY_STORE_DOMAIN='yourstore.myshopify.com'

Scroll to the bottom, hit "Select all" scopes for Storefront API access, and install the Shopify GraphiQL app that will help you to test your queries before you use them in your app. (Before proceeding with this step, add some sample products to your store and make sure they are available for the GraphiQL App sales channel). Now open the GraphiQL app, choose the Storefront API schema and paste this into the query field:

{
  products(first:5) {
    edges {
      node {
        id
      }
    }
  }
}

Inside the Next.js app, create a lib folder in the root directory and create a shopify.js file inside of it.

const domain = process.env.SHOPIFY_STORE_DOMAIN
const storefrontAccessToken = process.env.SHOPIFY_STOREFRONT_ACCESSTOKEN

async function ShopifyData(query) {
  const URL = `https://${domain}/api/2021-07/graphql.json`

  const options = {
    endpoint: URL,
    method: "POST",
    headers: {
      "X-Shopify-Storefront-Access-Token": storefrontAccessToken,
      "Accept": "application/json",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ query })
  }

  try {
    const data = await fetch(URL, options).then(response => {
      return response.json()
    })

    return data
  } catch (error) {
    throw new Error("Products not fetched")
  }
}

export async function getAllProducts() {
  const query = `
  {
  products(first: 25) {
    edges {
      node {
        id
        title
        handle
        priceRange {
          minVariantPrice {
            amount
          }
        }
        images(first: 5) {
          edges {
            node {
              originalSrc
              altText
            }
          }
        }
      }
    }
  }
}
`

  const response = await ShopifyData(query)

  const allProducts = response.data.products.edges ? response.data.products.edges : []

  return allProducts
}

What we are doing above:

  1. Creating a function called ShopifyData that will accept a query.

  2. ShopifyData it will make a POST request to the Shopify Storefront GraphQL API using the set headers and return the json response.

  3. ShopifyData function will return the data to the getAllProducts function which will set it equal to the allProducts variable.

To display products on the homepage, we add inside our index.js file:

import { getAllProducts } from "../lib/shopify"

export default function Home({ products }) {

  return (
    <div className="bg-white">
      <div className="max-w-2xl mx-auto py-16 px-4 sm:py-24 sm:px-6 lg:max-w-7xl lg:px-8">
        <h2 className="text-2xl font-extrabold text-gray-900 mb-6">
          Products
        </h2>
        <div className="grid grid-cols-1 gap-y-10 gap-x-6 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 xl:gap-x-8">
         {
            products.map(product => (
              <ProductCard key={product.node.id} product={product} />
            ))
          }
       </div>
      </div>
    </div>
  )
}

export async function getStaticProps() {
  const products = await getAllProducts()

  return {
    props: { products }, // will be passed to the page component as props
  }
}

Create a ProductCard.js component in a new folder called components:

import Link from 'next/link'
import Image from 'next/image'
import { formatter } from '../utils/helpers'

const ProductCard = ({ product }) => {
  const { handle, title } = product.node

  const { altText, originalSrc } = product.node.images.edges[0].node

  const price = product.node.priceRange.minVariantPrice.amount

  return (
    <Link
      href={`/products/${handle}`}
    >
      <a className="group">
        <div className="w-full bg-gray-200 rounded-3xl overflow-hidden">
          <div className="relative group-hover:opacity-75 h-72">
            <Image 
              src={originalSrc}
              alt={altText}
              layout="fill"
              objectFit="cover"
            />
          </div>
        </div>
        <h3 className="mt-4 text-lg font-medium text-gray-900">{title}</h3>
        <p className="mt-1 text-sm text-gray-700">{formatter.format(price)}</p>
      </a>
    </Link>
  )
}

export default ProductCard

What's happening above:

  1. We are using the getStaticProps function provided to us by Next.js to prefetch all the products from the getAllProducts function from our shopify.js file.

  2. Passing the products as a prop to our homepage function.

  3. Creating a ProductCard.js to display a single product card.

  4. Mapping over the products and displaying the ProductCard.js for each one.

Next Steps:

  1. Dynamic product pages using the getStaticPaths Next.js function.

  2. Create add-to-cart functionality using React Context for cart state management.

  3. Deploy to Vercel.

Last updated