E-Commerce for React Developers [w/ Next.js Shop Tutorial]

E-Commerce for React Developers [w/ Next.js Shop Tutorial]

I wrote this article for Snipcart. You can find the original version over at snipcart.com.

The events of 2020 totally fast-tracked the omnipresence of e-commerce in our lives.

It's changing the way we purchase goods and services that we use at a pace that would have been hard to imagine not so long ago.

From buying some swag from our favorite tech companies to fulfilling a prescription, the web needs tools to provide a dynamic experience where consumers can easily find what they're looking for and just as easily make the purchase.

In this post, I'll explore how one of these tools, React, can help developers create these high-quality e-commerce experiences.

I won't simply tell you that React can deliver dynamic UX, I'll also show you by crafting a Next.js shop in a step-by-step tutorial:

  • Creating a new app with Next.js
  • Adding products to the React app
  • Integrating a shopping cart
  • Defining products within Snipcart
  • Setting up a cart summary and cart preview

We all want to build e-commerce projects that stand out. Let's see how React can help.

Building a dynamic e-commerce experience

The crux of a shopping experience is being able to provide dynamic information to your site's customers. This includes both the product information of what you're trying to sell as well as how that relates to the actual customer.

The dynamic bits of products in e-commerce

When dealing with products, specifically physical goods, you might have a limited amount of products to actually sell. This means your shopping experience needs to be able to maintain an up-to-date count of how many items are left "in stock".

INGMARSON product listing page

Coupling that with the complexities of multiple people checking out simultaneously, it's critical that you're able to keep track of that quantity in real-time, otherwise you may run into situations where you end up overselling a product.

Pricing can also be a largely dynamic factor. Some may simplify it, where an item's price will always be a fixed amount, but you may find a use case where you want to change that price or provide a promotion to push your products.

The product page needs to reflect the cost that you ultimately charge the customer. While a cached price might be unintentional, you could quickly lose a customer's trust if they see a low price, only to end up being charged a different amount.

Providing a personalized e-commerce experience to customers

There are different levels of personalization we can provide customers who visit our website. Showing personalized product recommendations is a great way to help those visitors discover products they might not know exist.

But at a basic level, the core of any shopping experience that isn't limited to a single product checkout flow is being able to add items to a shopping cart and allowing the customers to manage that cart.

Snipcart powered cart in Uskinned Merch eCommerce theme for Umbraco

The shopping cart can include how many products someone wants to purchase, which products they wish to purchase, the total cost of all of those items, and the shipping cost depending on the address provided.

These details, along with the product information, all lend themselves to needing to provide a highly dynamic experience to help your customers through their checkout journey.

E-commerce in the world of React

Technology stacks in the e-commerce world are more traditionally server-backed. Given the highly dynamic nature, developers need to make sure that the personalized information is accurately provided to the customer on each page load.

Dynamic experiences in React

In the world of React, typical solutions involve serving a static application to a browser and hydrating it with client-side requests to provide a dynamic experience.

Unknowingly to the visitor, the app for a split second will be unpersonalized or even blank. Once the JavaScript and subsequent server requests load, the page will be updated with any dynamic information needed.

Similar to a traditional "serverful" solution, server-side rendering (SSR) is also an option with React, but you lose the benefits of serving a static app straight from storage with a CDN in front of it.

Building fast, scalable e-commerce websites

Providing a resilient web app should be a critical part of any solution, but it's even more critical in e-commerce.

Making sure your web app is available and functional has real currency attached to it. Those are real dollars lost to downtime if someone can't browse your product offerings or purchase those products.

This is what's given rise to the Jamstack, which brings dynamic features along with the benefits of a static app.

Benefiting from e-commerce on the Jamstack

We can provide that first byte to the browser statically from a CDN, which gives us tremendous benefits like fast page loads, infinite scalability, and a low hosting bill.

Example of how a CDN distributes requests

Each second---each millisecond---counts when serving an e-commerce app. Conversion rate is highly correlated to the amount of time it takes for a page to load in someone's browser.

It's also important to be able to scale up your store to the masses. You don't want your product page down when your new collection goes viral. That's lost money and a lost customer that may not return because of their poor shopping experience.

Leveraging React with e-commerce

And this is where React comes into play. React is a powerful library that gives us the ability to create dynamic experiences in the browser.

We can serve a completely static page to the browser and then load in the dynamic parts with those same client-side requests to provide realtime product data and a personalized shopping experience.

Loading and updating dynamic content in the browser

This becomes even easier with frameworks like Next.js and Gatsby. Both tools allow developers to statically compile the entire application, being able to provide the majority of a page's content with that first request, but then layer in anything that needs to be critically accurate.

For instance, most details of a product probably won't change. Sure, we might update the copy and fix errors, but those aren't critical to a real-time shopping experience.

We can statically compile those details to use tools like content management systems (CMS) that store that information where we would then pull that information into a framework like Next.js to display. If those details change, we can trigger a new build that will go out and fetch the latest information to show on our page.

For serving the dynamic details, like an up to date price of a product or an accurate tax calculation, we can make client-side requests to APIs that will ensure that we're always showing the right value. With this, we're leveraging the best of both worlds, providing a fast experience with real-time, dynamic details.

Creating an e-commerce shop with Next.js and Snipcart

React, Next.js, and Snipcartl

Now that we understand the benefits of building e-commerce stores with React, let's get into how we can craft them.

We're going to use Next.js to rapidly spin up a new React application where we can manage and display our products.

I also mentioned Gatsby earlier, remember? Well, the Snipcart team recently crafted an e-commerce recipe for this alternative React framework. You can read about it here.

We'll then layer in Snipcart, which will provide our shopping cart experience, allowing us to provide a way for people to purchase our products.

What you'll need to get started

Before getting started, we'll assume that you've already created a free Snipcart account. If you don't have an account, you can sign up here. It's forever free in "Test" mode.

You'll also need a basic understanding of JavaScript and React. While most of what you'll do includes plain HTML, we'll be working within a React application using Next.js.

Step 0: Creating a new React app with Next.js

We'll be using Next.js to create our React app. To do that, we can use npm to create a new app with the default Next.js template quickly.

First, navigate to the directory in your terminal that you want to create your new app in and run:

npx create-next-app next-snipcart-store

You can optionally replace next-snipcart-store with the name of the directory you want to create this project in.

This will create a new Next.js project and install the dependencies. Once it's finished, you can navigate to that directory and run the development command to start the server.

cd next-snipcart-store
npm run dev

Creating a new Next.js app

And once it's finished, you can now open up the project at localhost:3000!

Default Next.js template

Follow along with the commit in GH!

Step 1: Adding products to your new React app

To get started adding our products to the app, the first thing we need is a list of products.

Let's create a new file at the root of our project to store that product information that we can use throughout the app.

Create a new file called products.json and inside that file, simply add an empty array:

[]

When setting up our products, we need a few basic attributes:

  • Title: the human-friendly name of the product
  • ID: a unique identifier for that product
  • Description: a brief note about what the product is
  • Price: the cost of the item

We can create our first product by adding a new object inside of our empty array with the following:

{
  "title": "Snipcart Logo Sticker",
  "id": "sticker_logo",
  "description": "Show off your Snipcart support with a logo sticker!",
  "price": "2.00"
}

Here's what our file should look like at this point:

Products.json file

To use that file, we can go to our homepage file and import it.

Open up the pages/index.js file and add the following import statement at the top of the file:

import products from '../products.json';

With our products imported, we can now use them to display on the page.

Inside of <div className={styles.grid}>, Next.js includes some default links about Next.js. We're going to remove these and replace them with our own links.

Replace the grid with the following:

<div className={styles.grid}>
  {products.map(product => {
    return (
      <div key={product.id} className={styles.card}>
        <h3>{ product.title }</h3>
        <p>{ product.description }</p>
        <p>${ product.price }</p>
        <p>
          <button>Add to Cart</button>
        </p>
      </div>
    );
  })}
</div>

Here, we're looping through the products array that we imported. We're creating a new <div> for each product that includes a className that borrows the Next.js default styles for a card.

Inside of our <div>, we're including details about our product like the title and price, as well as adding a button that we can use to add the item to our shopping cart.

If we save the file and open up our browser, we can now see our first product.

Next.js app with product

Let's add a second product.

We can add another object to our project array for our second product:

{
  "title": "Snipcart Logo Sticker Pack",
  "id": "sticker_logo_pack",
  "description": "Get a pack of 3 Snipcart logo stickers.",
  "price": "4.00"
}

And if we save and reload our page, we see our second product.

Next.js app with 2 products

Finally, typically when we want to sell a product, we want to show an image of those products so our customers can see what the product looks like.

Let's add two image files to our project. Under the public directory, create a folder called "images", and add your image files there, one for each product.

I'm including two images, one for a single sticker and one for a pack of stickers.

Snipcart sticker image

Note: if you want to use the same image files, you can download them from the Git repository with this demo.

Inside of our products.json file, we now want to add those image files so we can grab them in our app.

Under "Snipcart Logo Sticker" add the following property:

"image": "/images/sticker-single.jpg"

And under "Snipcart Logo Sticker Pack" add:

"image": "/images/sticker-3pack.jpg"

Then, back inside pages/index.js, above our product title, add:

<img src={product.image} alt={`Preview of ${product.title}`} />

And if we save and reload the page, we see we have our images, but they're huge!

To fix the image sizes, you can open up styles/global.css and add the following rule:

img {
  max-width: 100%;
}

And now we have our page with our two products!

Snipcart sticker products

Follow along with the commit on GH!

Step 2: Adding a Snipcart shopping cart to your React app

The first part of integrating Snipcart includes importing a few files from the Snipcart public CDN.

Inside of pages/index.js, the default Next.js template comes with a <Head> component that allows us to add additional tags and scripts to the <head> of our page.

Inside of the component, add the following:

<link rel="preconnect" href="https://app.snipcart.com" />
<link rel="preconnect" href="https://cdn.snipcart.com" />
<link rel="stylesheet" href="https://cdn.snipcart.com/themes/v3.0.21/default/snipcart.css" />

This is going to tell the browser to start a connection to the two of Snipcart's subdomains, which will help with performance. We're also including a CSS file that contains the Snipcart styles for the shopping cart.

Next, as the bottom of the file, right after the <footer>, add the following:

<script async src="https://cdn.snipcart.com/themes/v3.0.21/default/snipcart.js" />
<div hidden id="snipcart" data-api-key="[YOUR-API-KEY]" />

Here, we're including the Snipcart script that will provide all of our shopping cart's functionality. We're also including a hidden <div> where we need to specify our API key from our account.

To find the API key, inside of your Snipcart account, navigate to your account settings, find the API Keys page, and then copy the Public Test API Key under Credentials.

Snipcart API Key

Copy that value and replace [YOUR-API-KEY] in the snippet above with your key:

<div hidden id="snipcart" data-api-key="123456789012345678901234567890" />

At this point, if we save and reload the page, we shouldn't notice any difference.

Snipcart sticker products

Follow along with the commit in GH!

Step 3: Setting up the products to add to the Snipcart shopping cart

In order to let people add our products to their shopping cart, we need to add a few attributes to our product buttons.

Let's update our Add to Cart button to the following:

<button className="snipcart-add-item"
  data-item-id={product.id}
  data-item-image={product.image}
  data-item-name={product.title}
  data-item-url="/"
  data-item-price={product.price}
>
  Add to Cart
</button>

With these attributes, Snipcart can dynamically look at our products and be able to find out the details about each of them. Additionally, because we're adding the class selector, Snipcart can now transform our buttons into working buttons allowing us to actually add our items to the shopping cart.

Adding product to Snipcart shopping cart

As we can see, Snipcart knows exactly what product we added to our cart by looking at the attributes on our button!

Follow along with the commit in GH!

Similar to how we set up our products to easily add them to our Snipcart shopping cart, we can create a link that lets our customers visit that cart page. We can also show an up to date total cost so that our customers always know how much they're looking to spend.

To do this, we're going to take advantage of the existing description on the page inside of <p className={styles.description}>.

Let's replace that paragraph tag with:

<p className={styles.description}>
  <a className="snipcart-checkout snipcart-summary" href="#" style={{textDecoration: "none"}}>
    <strong>Cart:</strong> <span className="snipcart-total-price">$0.00</span>
  </a>
</p>

First, we're adding a new link including class selectors, that will tell Snipcart that we want to use our link as a container for our cart summary. We're also telling it that we want this link to open up our shopping cart.

Inside, we're adding a label of "Cart".

Next to that, we're including a separate <span> with its own class selectors that will let Snipcart dynamically update that value with the current total of our customer's cart.

If you notice, we're including $0.00 inside of our <span>. This will allow our page to show a value before the JavaScript loads to avoid layout shifts when possible.

Finally, while we're here, let's update the page's title inside of the <h1> tag to something that reflects our store.

I'm going to update it to "Snipcart Store":

<h1 className={styles.title}>
  Snipcart Store
</h1>

If we refresh the page, we can see our updated title. But if we add one of the products to the cart and close the shopping cart, we can see our cart's updated total cost. We can even click on our Cart link, which will open back up our cart!

Next.js React app with Snipcart

Follow along with the commit in GH!

Next Steps

Hosting and deploying your store

There are a variety of options available for hosting and deploying your Next.js app. Vercel, the team that maintains Next.js, comes with a lot of functionality "out of the box" that allows you to host and deploy a Next.js app easily.

If you plan on going with another static provider, such as Netlify, you'll want to configure the project's build script to export the compiled app as static files. To do this, you can update your build script inside of package.json to be:

"build": "next build && next export",

Now, whenever a build is run, you will have static files available in the out directory.

Setting up and managing your products

If you followed along, you might have used the sample products from the demo. At this point, you can update the products inside products.json to include the products your store is actually offering.

For a more advanced solution, you can ingest the product information from an external source like a custom CMS!

Customizing your store

For this walkthrough, we took advantage of pretty much all of the styles already built into the default Next.js template. This might not look exactly like your brand or how you imagine your store.

With Next.js, we can use most CSS solutions, including standard CSS, to customize our page how we want it, whether it's merely updating the buttons to look a little nicer or completely rebranding the store.

Example Style Updates

Taking your store live

In our setup, we used a test API key to make sure our shopping cart worked as expected. This allows us to actually process transactions like we would in the real world.

In order to take your store live, you'll first need to make sure you have payments set up with your Snipcart account.

Once you're ready to go, you can update your account into Live mode, which will allow you to start selling your products to the world!

Live demo & GitHub repo

Demo of Snipcart checkout

Try out the live demo here

See the GitHub repo here

Closing Thoughts

E-commerce is a complicated space, requiring highly dynamic content that will scale to the customers visiting our stores.

With React and Next.js, we can provide a static app that will be able to survive large influxes of traffic when a product goes viral, all while being able to provide an interactive experience for people to buy our products.

Using Snipcart, we can confidently provide a shopping experience tailored to our product offering that's personalized to each customer. Snipcart lets us handle the entire checkout flow all in the browser allowing people to quickly and securely make a payment.

By leveraging these tools, we can bring the dynamic experiences needed in the e-commerce world to the static web.

Originally published at https://snipcart.com/blog/react-ecommerce-tutorial