
Grab your gear: The official Sanity swag store
Read Grab your gear: The official Sanity swag storeI 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:
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'}]
}
]
}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>
);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;Your existing pages/product/[slug].js should continue to work as-is, since you're just adding a new layer of navigation above it.
/) now shows categories/category/[slug]) shows products filtered by that category/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!
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.
Content operations
Content backend


The only platform powering content operations
By Industry


Tecovas strengthens their customer connections
Build and Share

Grab your gear: The official Sanity swag store
Read Grab your gear: The official Sanity swag store