Building an e-commerce website with Sanity.io
Table of contents
Motivation
This is a project that leverages Sanity’s headless CMS. The idea is that the store owner (who doesn’t code) is able to control the content of their store, while developers build the front-end according to their needs. What is good about Sanity is that developers do not have to worry about back-end and database integration as that is already handled by Sanity. All devs need to do is provide the schema, and the appropriate fields will be displayed in Sanity studio. Sanity studio is a UI where administrators (store owners) can go and edit the contents. In order to fetch data from Sanity, devs need to use Groq query syntax, which is quite similar to GraphQL.
How to set up the project?
First we need to decide the basic tech stack that we wanna use for the project. Following are what I decided to use:
- Next.js 13 (keep in mind that this is still experimental)
- TypeScript
- TailwindCSS
Then, we will create a guide or boilerplate that we can refer to, should we have similar projects in the future.
Set up Next JS
- First off, we want to bootstrap a NextJS project with Tailwind and TypeScript. Lucky for us, Tailwind provided us guides in their docs. We can follow the steps there to set up the project.
- Now we should have a NextJS project with Tailwind and TypeScript properly configured (hopefully). This can be tested by implementing some tailwind styling and check if the styles are applied in the UI.
Set up Sanity.io
- Next, we will set up Sanity. We will use the free boosted plan by Papafam.
npm create sanity@latest -- --coupon sonny2022
- We will start a clean project (no schema or dataset). We will do that ourselves so that we have a better understanding on how to use Sanity.
- Before we tinker around with Sanity schema, let’s integrate Sanity studio with Next.js first.
Integrate Sanity with NextJS
- First we need to install an npm package provided by sanity, next-sanity
- To integrate Sanity into Next, we are gonna copy some of the packages inside Sanity’s project package.json into the main Next package.json. Following are the packages we are gonna port over and install in our root directory:
"sanity/vision": "^3.0.0"
"sanity": "^3.0.0",
"styled-components": "^5.2.0”
"@sanity/eslint-config-studio": "^2.0.1",
- Port over sanity configs to the root folder;
sanity.cli.ts
& sanity.config.ts
as well as schemas folder. Sanity project folder can now be removed.
- Refactor the config files by putting the variable inside env file;
.env.local
- Create a theme by specifying the color palettes of your choice
- Inside app directory, create a route for studio;
(admin)/studio/[[…index]]/page.tsx
and set up the necessary stuff including the theme. We can refer to next-sanity
‘s doc at npmjs.
- Once everything is set up (head.tsx, loading.tsx, etc.), visit /studio page and we will get a popup regarding CORS. Just click on the Continue button and add the FE url as a CORS origin to your Sanity project.
- Now we are able to view the studio, but since we chose to start from a clean slate we wouldn’t see anything but an empty page, except for a few stuff in the navigation. If you play around, you will notice that the theme has been applied!
Create schemas
- To do this, we refer to lilinandco.com and create the schemas based on what they have on their UI. The basic ones are product, size, category, etc.
- After creating the schemas, we should now be able to view some meaningful content and populate the relevant fields in Sanity studio.
- Take some time to populate the products with dummy data to be used for our FE later on.
Build your UI
- Before we dive into building the UI, it would be good if we could implement the live preview first, so that any changes on the UI can be immediately reflected. This can also be found in next-sanity docs.
- Then, start creating UIs. I refer to lilinandco.com and replicate theirs, using tailwindCSS and making sure it is responsive. Do the mobile-first approach.
- Once UI is in place, we can start implementing business logics like the quantity of selected items, the size, etc. Since Next 13 uses server-side components by default, we need to make sure that we use the
“use client”
directive to use hooks.
Integrate Stripe API
- Create api endpoint for checkout sessions and also implement webhooks. This can be achieved by referring to Vercel’s guide
- At this point, just hardcode the line-items and make sure items are all there in the cart when the checkout-sessions API endpoint is triggered.
Set up global state management
- I almost always go for Zustand for personal projects like this, but since Redux is the industry gold standard at this point in time, I decided to relearn and implement it in this application.
- The reason why I moved away from Redux was because of the amount of boilerplate code, and the fact that they have many different moving parts like reducers and actions. In my opinion, it is too complicated, and not worth the hassle for a relatively smaller project like this. However. this problem is kinda solved with redux toolkit. A lot of boilerplate can be reduced, and the usage is quite similar to Zustand.
- Unlike Zustand, it doesn’t come with persistence feature. So I had to use another library called
redux-persist
for it. I don’t really fancy this because the library does not have active development.
- Now that we have centralized the cart state, we are able to manipulate the data structure and send the correct items to stripe checkout-sessions API endpoint and remove the hardcoded line-items.
- Now we should be able to test the checkout feature.
Deployment
- Last but not least, we will deploy our application to Vercel. It will come with the studio since Sanity provides the hosting for it, so we don’t need to worry about that.
- Remember to set up the environment variables for both FE and BE. For FE, we need to set up the Stripe API keys, and for BE, we need to set up the Sanity API keys and Stripe API keys.