TreyzaHelp Center
Theme Editor

Treyza SDK: Product Card Slot

The product card is a slot component: the storefront hands you the product data and the add-to-cart / favorite / compare actions ready-made; you only…

Where: Theme Editor → left panel Components tab → Generate a component with AI → Component type: Product card. Also right panel Product tab → Product Card → Custom cards. For whom: Merchants who want the product list card to go beyond the five built-in options, and the designers who write cards for them In short: The product card is a slot component: the storefront hands you the product data and the add-to-cart / favorite / compare actions ready-made; you only write what the card looks like. The card is produced in the Component Studio, previewed with your real products, becomes selectable in Product Card settings after Publish, and can be shared with the community.


What is a slot component?

A page block (promo strip, FAQ…) is added to a page and stands on its own. A product card instead fills a slot the storefront already draws: in category, search, featured and related product lists the same card is drawn for every product, dozens of times. Therefore the card:

  • fetches no data — product, price, image, badges, stock, pre-order and color variants arrive as props,
  • writes no actions — add to cart, favorite, compare and quick view come as ready host components,
  • renders on the server — Google sees the card in the first HTML, the browser hydrates it,
  • never leaves the visitor with an empty box on error; the storefront falls back to the built-in Classic card for that product.

PRODUCT_CARD is the first slot. Other slots such as the cart drawer will be added later with the same mechanism.


Where does a card start?

Choosing Product card as the Component type in the studio opens two paths:

  1. Start from an official template — Classic, Minimal, Overlay, Editorial and Compact are listed as open source templates. Clicking one creates a copy in your name and builds it; then ask the AI for changes ("make the title bigger", "price in red") or write directly in the Code tab of the right panel (the preview updates as you type, see below). The storefront's built-in five cards are fed from the same templates, so your copy is exactly the production code.
  2. Generate with AI — describe the card in plain words. The AI knows the product card contract; it does not invent fields, reads the data from props and uses the host buttons.

Both paths go through the same pipeline: code check → build → validation gate (automatic renders with discounted, variant, bundle, out-of-stock, pre-order, imageless and very-long-name products).


Preview, publish and select

  • The live preview in the middle panel renders with your store's real products. The desktop/mobile switch narrows the grid.
  • Editing the code directly: the Code tab in the right panel is writable for product cards. About a second after you stop typing, the code is compiled on the server through a fast path (code check + browser bundle + CSS; no version, no validation gate) and the preview re-renders; the bar above reads "Preview up to date · N ms". Broken code does not break the preview: the last working state stays and the errors are listed under the code. Save (Ctrl+S) stores the code permanently and starts the persistent build and the validation gate; the storefront still renders only the published version. The code of a card under review or published to the community is locked.
  • After an AI turn the new code is previewed through the same fast path before the persistent build finishes; once the build completes, the preview switches to the built version.
  • Once built, a Publish button appears at the top. Publishing does not share the card with the community; it only makes it selectable in your store. Later changes do not reach the storefront until you publish again; the storefront always draws the latest published version.
  • Use as store card switches the Product Card setting to this card. You can do the same from the right panel: Product → Product Card → Custom cards, which lists your published cards and the ones installed from the community.
  • It can also be chosen per block: the Card type setting of the Product List, Curated Strip, Shipping Threshold Progress (suggestions variant) and Empty Search State (recommendations variant) blocks offers Store setting, which follows the Product Card setting; your custom cards are listed below the built-in types. The recommended products on the cart page always use the store card.
  • Unpublish makes the card unselectable in your store; code and versions are kept.
  • Versions (Status tab): every successful build is a new version; the one published in your store carries the published badge and the one approved for the community the approved badge. Restore this version returns the card to that version's code and bundle under a new version number; the publication does not change, press Publish to put the restored version on the storefront. The current, published and approved versions cannot be deleted; delete the others with the trash icon.
  • Wide cards: a card that declares export const treyza = { contract: 1, slot: "PRODUCT_CARD", wide: true } (like the Compact template) is drawn in a narrow column on the storefront grid, at most four columns on wide screens; the Custom cards list shows a "Wide" badge.
  • The card appears on the My Components page with a "Product card" badge.

If an unpublished or deleted card stays selected, the storefront silently falls back to Classic; the Product Card setting and the block settings show this with a yellow warning.


Sharing with the community and installing

Share the card from the Status tab with Send to community; the approval gate and locks described in Sharing a Component with the Community apply unchanged. When another merchant sees your card in the Community tab and presses Install, it lands in that store's Custom cards list; an installed card always renders the approved version, even if you change it later.


The data the card receives — ProductCardProps

The card is a single-argument React component taking its types from the @treyza/sdk/slots/product-card entry:

"use client";
import type { ProductCardMeta, ProductCardProps } from "@treyza/sdk/slots/product-card";

export const treyza: ProductCardMeta = { contract: 1, slot: "PRODUCT_CARD" };

export default function MyCard({ product, view, settings, state, actions, labels, ui, format, priority }: ProductCardProps) {
    const { Link, Media, AddToCartButton, CompareToggle, FavoriteToggle, ColorSwatches, CardBadgeLayer } = ui;
    return (
        <div className="group relative flex flex-col overflow-hidden rounded-xl border bg-card">
            <Link href={view.url}>
                <Media>
                    <CardBadgeLayer
                        discountLabel={view.discountLabel}
                        outOfStockLabel={view.isOutOfStock ? labels.outOfStock : null}
                        preOrderLabel={product.isPreOrder && !view.isOutOfStock ? labels.preOrder : null}
                        badges={product.badges}
                    />
                </Media>
            </Link>
            <FavoriteToggle className="absolute right-2.5 top-2.5" />
            <div className="flex flex-col gap-1.5 p-3">
                <Link href={view.url} className="line-clamp-2 text-sm font-medium">{product.name}</Link>
                <span className="text-base font-bold">{view.priceLabel}</span>
                {view.listPriceLabel && <span className="text-xs line-through text-muted-foreground">{view.listPriceLabel}</span>}
                <AddToCartButton className="w-full" />
                <CompareToggle className="w-full" />
            </div>
        </div>
    );
}
FieldContents
productRaw product data: name, slug, price.salePrice / listPrice, pictures, gallery (image/video), brand, reviewSummary, stock, noStockContinueBuying, type (BASIC / VARIANT / BUNDLE), bundleSummary, isPreOrder, badges (the merchant's custom badges), colorVariants, mainVariant
viewFields derived by the storefront: url, isOutOfStock, isVariant, isBundle, requiresSelection, isPreOrder, discountPercent, discountAmount, discountLabel (per the store's percent/amount setting), priceLabel, listPriceLabel, rating.label, primaryImage, gallery, colorVariants, mainVariantValues, ratioStyle
settingscurrency, locale, discountType, aspectRatio, productUrlPrefix, showVariants, compareEnabled, favoritesEnabled
stateisFavorite, isCompared, activeColor, addToCartStatus (idle / loading / success)
actionsaddToCart(), toggleFavorite(), toggleCompare(), openQuickView(), selectColor(name) — when you write your own buttons
labelsTranslated texts: addToCart, addedToCart, preOrder, preOrderButton, outOfStock, favoriteAdd, favoriteAdded, compareAdd, compareAdded, quickView, colorOptions, moreColors
uiHost components (below)
formatcurrency(n) and number(n, options) — formatted for the store locale
prioritytrue for first-row cards; ui.Media applies image priority itself

Host components — ui.*

ComponentWhat it does
LinkLink to the product page; the storefront resolves the store's product URL prefix
MediaProduct image: aspect ratio, second image/video on hover, priority loading. children is for the badge layer
AddToCartButtonAdd to cart / pre-order; opens quick view for variant and bundle products, disables itself when out of stock
CompareToggleCompare entry; renders nothing when the store setting is off
FavoriteToggleFavorite heart; renders nothing when favorites are off
ColorSwatchesColor dots; a selection changes view.primaryImage, overflow opens quick view
CardBadgeLayerPlaces discount, out-of-stock, pre-order and custom badges in the corners; supports layout="overlay" and density="compact"

Limits

  • Allowed imports: @treyza/sdk/slots/product-card, @treyza/sdk/ui, @treyza/sdk/primitives, @treyza/sdk/lib/utils, react, @tabler/icons-react (icons by name, one by one), clsx, tailwind-merge.
  • Forbidden: @treyza/sdk/data (the card fetches nothing), fetch and any network access, window / document / localStorage / location, eval, dangerouslySetInnerHTML, dynamic import(), constructor / __proto__ / prototype access. The code check rejects these before the build and explains why.
  • configSchema is not used; the card's settings come from the store's Product Card settings.
  • Prefer theme tokens over fixed colors (bg-card, text-foreground, text-muted-foreground, bg-primary…) so the card follows the store's color and corner radius settings.
  • The card renders on the server: no dates, random values or DOM access during the first render.
  • Hover layers do not exist on mobile: draw the desktop layer inside hidden md:block and separate mobile buttons inside md:hidden.
  • Every card should contain one CompareToggle and one FavoriteToggle; they hide themselves when off.

FAQ

I changed my card but the storefront does not show it. The card may have been rebuilt but not published; press Publish in the top bar. The storefront draws the latest published version. What you type in the Code tab becomes permanent only after Save; unsaved code is visible only in the studio preview.

I typed in the Code tab, why did the preview not update? Check the error list under the code: code that fails the check or does not compile leaves the preview on the last working state. Once the error is fixed the preview refreshes by itself.

Do the official templates change? No; the Classic…Compact templates are read from the package and always copied. However much you change your copy, the template stays the same and a new copy opens from the original code.

What if the card fails for a single product? Only that product falls back to the built-in Classic card; the rest of the list is unaffected and the error is logged for the store.

Does a card installed from the community update? No; it stays on the author's approved version. A new version requires the author to resubmit and get approval.

Was this page helpful?

On this page