Next.js Conf 2024: Your app should be Live by Default – Watch Keynote

Adding category schema to index page in Sanity e-commerce site

17 replies
Last updated: Jul 7, 2022
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.
Jul 7, 2022, 7:38 AM
Product

export default {
  name: 'product',
  title: 'Product',
  type: 'document',
  fields: [
    {
      name: 'title',
      title: 'Title',
      type: 'string',
    },
    {
      name: 'slug',
      title: 'Slug',
      type: 'slug',
      options: {
        source: 'title',
        maxLength: 96,
      },
    },
    {
      title: 'Default variant',
      name: 'defaultProductVariant',
      type: 'productVariant',
    },
    {
      title: 'Variants',
      name: 'variants',
      type: 'array',
      of: [
        {
          title: 'Variant',
          type: 'productVariant',
        },
      ],
    },
    {
      title: 'Tags',
      name: 'tags',
      type: 'array',
      of: [
        {
          type: 'string',
        },
      ],
      options: {
        layout: 'tags',
      },
    },
    {
      name: 'categories',
      title: 'Categories',
      type: 'array',
      of: [
        {
          type: 'reference',
          to: {type: 'category'},
        },
      ],
    },

  ],

  preview: {
    select: {
      title: 'title',
      media: 'defaultProductVariant.images[0]',
    },
  },
}
Jul 7, 2022, 7:39 AM
export default {
name: 'product',
title: 'Product',
type: 'document',
fields: [
{
name: 'title',
title: 'Title',
type: 'string',
},
{
name: 'slug',
title: 'Slug',
type: 'slug',
options: {
source: 'title',
maxLength: 96,
},
},
{
title: 'Default variant',
name: 'defaultProductVariant',
type: 'productVariant',
},
{
title: 'Variants',
name: 'variants',
type: 'array',
of: [
{
title: 'Variant',
type: 'productVariant',
},
],
},
{
title: 'Tags',
name: 'tags',
type: 'array',
of: [
{
type: 'string',
},
],
options: {
layout: 'tags',
},
},
{
name: 'categories',
title: 'Categories',
type: 'array',
of: [
{
type: 'reference',
to: {type: 'category'},
},
],
},

],

preview: {
select: {
title: 'title',
media: 'defaultProductVariant.images[0]',
},
},
}
Jul 7, 2022, 7:40 AM
productVariant

export default {
  title: 'Product variant',
  name: 'productVariant',
  type: 'object',
  fields: [
    {
      title: 'Title',
      name: 'title',
      type: 'string',
    },
    {
      title: 'Price',
      name: 'price',
      type: 'number',
    },
    {
      title: 'SKU',
      name: 'sku',
      type: 'string',
    },
    {
      name: 'images',
      title: 'Images',
      type: 'array',
      of: [
        {
          type: 'image',
          options: {
            hotspot: true,
          },
        },
      ],
    },
  ],
}
Jul 7, 2022, 7:41 AM
category

export default {
  name: 'category',
  title: 'Category',
  type: 'document',
  fields: [
    {
      name: 'title',
      title: 'Title',
      type: 'string',
    },
    {
      name: 'slug',
      title: 'Slug',
      type: 'slug',
      options: {
        source: 'title',
        maxLength: 96,
      },
    },
    {
      name: 'description',
      title: 'Description',
      type: 'text',
    },
    {
      name: 'parents',
      title: 'Parent categories',
      type: 'array',
      of: [
        {
          type: 'reference',
          to: [{type: 'category'}],
        },
      ],
    },
  ],
}
Jul 7, 2022, 7:41 AM
You'll want to change the query here to get categories instead of products. You'll then need to create another page for displaying products by category.
Jul 7, 2022, 4:40 PM
That is so helpful, thank you!!!
Would you mind giving me an example of how the new page might look? I can figure out the jsx, im just more confused about the static props and importing scripts etc
Jul 7, 2022, 4:44 PM
It's going to be quite similar to the existing product page , but again you'll want to replace any 'product' specific things with your 'category'. Just spitballing, but this can get you started:
import React, { useState } from 'react';

import { client, urlFor } from '../../lib/client';
import { useStateContext } from '../../context/StateContext';

const CategoryDetails = ({ category, allCategories }) => {
  //your component
}

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 }}) => {
  const query = `{
    "category": *[_type == "category" && slug.current == '${slug}'][0]{
       ...,
       parents[]->
     },
    "allCategories": *[_type == "category"]{
       ...,
       parents[]->
     },
  }`
  
  const data = await client.fetch(query);

  return {
    props: data
  }
}

export default ProductDetails
Jul 7, 2022, 4:54 PM
Beautiful. So where would the jsx go? Inside where you put //your component?
Also, does this code ensure that when they click a product on the product categories page it will bring them to the correct product? Or is there something else I need to add for this?
Jul 7, 2022, 5:03 PM
And will this page hold my carts state data? So like if they add something to cart, then press home and go to a different category, all their cart info will still be there?
Jul 7, 2022, 5:05 PM
I just don't want to break any functionality by trying to implement a new one lol I'm sorry I'm really new to this tech
Jul 7, 2022, 5:05 PM
I haven't added any of that functionality to this page. You'll have to play around, look at the product example, and build that out. I have showed you how to get the data out of Sanity though!
Jul 7, 2022, 5:07 PM
Got it. I'll figure it out. I really appreciate all your help. I have another thread open if you know anything about this as well, I just need a point in the right direction. https://sanity-io-land.slack.com/archives/C9Z7RC3V1/p1657209045403439?thread_ts=1657209045.403439&cid=C9Z7RC3V1
Jul 7, 2022, 5:10 PM
Sure thing! I'll take a look at it today!
Jul 7, 2022, 5:11 PM
I would add the jsx where you left a note in the code above at //your component ?
Jul 7, 2022, 5:14 PM
Yes! Your JSX and any other functionality you need on your frontend would go there.
Jul 7, 2022, 5:47 PM
You've saved me hours of struggling through some of this, I really appreciate it
Jul 7, 2022, 5:49 PM
Happy to help get you pointed in the right direction!
Jul 7, 2022, 5:50 PM

Sanity– build remarkable experiences at scale

Sanity is a modern headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.

Was this answer helpful?