Product page

It is mandatory to include a product.json file in the pages directory. You can create additional variations such as product.shoes.json, product.clothes.json, etc. Within the Merchant panel, theme users can choose which variation to apply to each product.

Additionally, the product page features a unique data hook, useProduct(), which retrieves the specific product based on the URL.

There are few other hooks available to provide the full functionality of the product page. These are:

useSelectedVariant(), this hook significantly reduces the hassle of variant selection in product pages.

useCartItemQuantity(), this hook lets you add, delete, decrease products in the cart.

Show product details

Use useProduct() hook to show various details about the product.

import {useProduct} from "builderoo";
 
const product = useProduct()

Learn more about the useProduct() hook.

Handle option selection

Use the useSelectedVariant() hook to handle option selection. As the user selects an option, call onSelectOption() function. This hook internally keeps track of selection/de-selection of options and returns the variant property with the variant value. If there’s no variant available for the combination of the selected options the value of variant becomes null.

import { useProduct, useSelectedVariant} from "builderoo";
 
// Component
const product = useProduct()
const {variant, onSelectOption, isOptionSelected} = useSelectedVariant(product)

A complete example is available later on this page.

Spotlight the appropriate media

The useSelectedVariant() hook also returns two other properties.

  1. preferredMedia: As you select options and call onSelectOption function, the preferredMedia contains the media item from product.media that best matches with the selected options.

  2. setPreferredMedia: When the user manually selects a media item, you can use setPreferredMedia to set currently spotlighted media item. This method is only provided to avoid complexity in maintaining another state variable to spotlight a media item.

import { useProduct, useSelectedVariant} from "builderoo";
 
// Component
const product = useProduct()
const {variant, onSelectOption, isOptionSelected, preferredMedia, setPreferredMedia} = useSelectedVariant(product)

Add to cart

Use useCartItemQuantity() to show how many products are already in the cart, and to add/delete the product from the cart.

import {useCartItemQuantity} from "builderoo";
 
const {add, remove, set, count} = useCartItemQuantity(productId, variantId)
 
// Now add 1 item to the cart
add(1)
 
// remote the item from the cart
remove()
 
// set quantity of the product to a specific number
set(3)
 

Full example

Here’s a full example of using various hooks to make the product page.

sections/ProductDetail.jsx
import React, {useState} from 'react';
import { useProduct, useCartItemQuantity, useSelectedVariant} from "builderoo";
import classNames from "clsx";
 
export default function ProductDetail() {
  const product = useProduct()
  const {variant, onSelectOption, isOptionSelected} = useSelectedVariant(product)
  const {add, remove, set} = useCartItemQuantity(product, variant)
 
  const [quantity, setQuantity] = useState(1)
 
  return (
    <div>
      <section className="px-20 pt-10 grid grid-cols-2 gap-10">
        <div className="">
          <div>
            <img src={product.image} />
          </div>
        </div>
        <div className="flex flex-col">
          <h3 className="font-medium text-2xl">{product.title}</h3>
          <div className="font-medium text-lg mt-2">{product.price} /></div>
          <ul className="space-y-3 mt-4">
            { product.options && product.options.length > 0 && product.options.map((option, i) => (
              <li key={i} className="mb-4">
                <div className="text-sm text-gray-600 mb-2">{option.name}</div>
                  <ul className="flex gap-3">
                    { option.values.map((value, i) => (
                      <li
                        onClick={() => onSelectOption(option._id, value._id)}
                        key={i}
                        className={classNames(
                          "border border-gray-300 rounded-sm px-3 py-1 text-sm cursor-pointer",
                          {"bg-black text-white": isOptionSelected(option._id, value._id)},
                          {"bg-muted-background text-black": !isOptionSelected(option._id, value._id)},
                        )}>
                        {value.label}
                      </li>
                    ))}
                  </ul>
              </li>
            ))}
          </ul>
          <div className="mt-10 mb-24 flex items-center gap-4">
            <button onClick={() => add(1)} disabled={variant == null}>Add to cart</button>
          </div>
        </div>
      </section>
      <section className="mt-10 px-20 text-subtle">
        {product.description}
      </section>
    </div>
  );
}

Example of the product page using this section:

pages/index.json
{
  "schema": "https://builderoo.dev/schema/page.json",
  "layout": {
    "component": "DefaultLayout"
  },
  "sections": [
    {
      "component": "ProductDetail"
    }
  ]
}