How to add category schema to index page in Sanity e-commerce site?

17 replies
Last updated: Nov 29, 2025
Hi, I used this repo: https://github.com/adrianhajdin/ecommerce_sanity_stripe to build an ecommerce site's structure following his youtube tutorial. However, the only real difference is I decided to use some of the standard e-commerce schemas already built in rather than making my own schema as he did. My question is how could I take the structure of this site and add the category schema to the index page? I want to put categories on the home page rather than listing all of my products on the home page. Then when you click the category it brings you to a new page of the site that will only show products in that category. Which will then lead to the single products page. All of which is being hooked dynamically... If you click the repo you can scroll down to see images of the product page for reference.
Could someone pretty please help me type up something that will help me achieve this? I will post my exact schema and category files in the comments of this thread.
AI Update

I can help you restructure your e-commerce site to display categories on the home page instead of all products! This is a common pattern for e-commerce sites and works great with Sanity's flexible content structure.

Here's how to achieve this:

1. Schema Setup

First, make sure your product schema references categories. Your product schema should include a reference to categories:

// schemas/product.js
export default {
  name: 'product',
  title: 'Product',
  type: 'document',
  fields: [
    // ... other fields
    {
      name: 'category',
      title: 'Category',
      type: 'reference',
      to: [{type: 'category'}]
    }
  ]
}

2. Update Your Home Page (index.js)

Modify your getServerSideProps or getStaticProps to fetch categories instead of products:

// pages/index.js
import { client } from '../lib/client';

export const getStaticProps = async () => {
  // Fetch categories instead of products
  const categoriesQuery = '*[_type == "category"]';
  const categories = await client.fetch(categoriesQuery);

  return {
    props: { categories }
  }
}

const Home = ({ categories }) => (
  <div>
    <div className="products-container">
      {categories?.map((category) => (
        <Link href={`/category/${category.slug.current}`} key={category._id}>
          <div className="product-card">
            <img 
              src={urlFor(category.image)}
              width={250}
              height={250}
              className="product-image"
            />
            <p className="product-name">{category.name}</p>
          </div>
        </Link>
      ))}
    </div>
  </div>
);

3. Create a Dynamic Category Page

Create a new file pages/category/[slug].js to display products filtered by category:

// pages/category/[slug].js
import React from 'react';
import { client } from '../../lib/client';
import { Product } from '../../components'; // Reuse the Product component

const CategoryPage = ({ products, category }) => {
  return (
    <div>
      <div className="products-heading">
        <h2>{category.name}</h2>
        <p>{category.description}</p>
      </div>

      <div className="products-container">
        {products?.map((product) => (
          <Product key={product._id} product={product} />
        ))}
      </div>
    </div>
  );
};

export const getStaticPaths = async () => {
  const query = `*[_type == "category"] {
    slug {
      current
    }
  }`;
  
  const categories = await client.fetch(query);
  
  const paths = categories.map((category) => ({
    params: { 
      slug: category.slug.current
    }
  }));

  return {
    paths,
    fallback: 'blocking'
  }
}

export const getStaticProps = async ({ params: { slug } }) => {
  // Fetch the category details
  const categoryQuery = `*[_type == "category" && slug.current == '${slug}'][0]`;
  const category = await client.fetch(categoryQuery);
  
  // Fetch products that reference this category
  const productsQuery = `*[_type == "product" && references(*[_type=="category" && slug.current == '${slug}']._id)]`;
  const products = await client.fetch(productsQuery);

  return {
    props: { products, category }
  }
}

export default CategoryPage;

4. Keep Your Existing Product Page

Your existing pages/product/[slug].js should continue to work as-is, since you're just adding a new layer of navigation above it.

Key Points:

  • Home page (/) now shows categories
  • Category page (/category/[slug]) shows products filtered by that category
  • Product page (/product/[slug]) shows individual product details (unchanged)

The GROQ query *[_type == "product" && references(*[_type=="category" && slug.current == '${slug}']._id)] is doing the heavy lifting here - it finds all products that reference the category you're viewing.

You can reuse most of the styling and components from the adrianhajdin/ecommerce_sanity_stripe repo, just swap out what data you're fetching and displaying on each page. The Product component from the tutorial can be reused on your category pages to maintain consistent styling.

If you're using Next.js 13+ with the App Router instead of the Pages Router, the structure would be similar but using app/category/[slug]/page.js instead. Let me know your schema files and I can help you refine this further!

Show original thread
17 replies

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?