Skip to main content

Documentation Index

Fetch the complete documentation index at: https://86d.app/docs/llms.txt

Use this file to discover all available pages before exploring further.

The products module is the foundation of every 86d store. It manages your full product catalog (including variants, hierarchical categories, and collections) with read-only storefront browsing and full admin CRUD. You get paginated listing, full-text search, featured products, related-product scoring, and CSV import out of the box. Source: modules/products · npm: @86d-app/products

Installation

npm install @86d-app/products
Then register the module in your store’s config.json:
{
  "modules": ["@86d-app/products"]
}

Configuration

Pass options to the factory when you register the module:
import products from "@86d-app/products";

const module = products({
  defaultPageSize: 20,
  maxPageSize: 100,
  trackInventory: true,
});
defaultPageSize
number
default:"20"
Default number of products returned per page on listing endpoints.
maxPageSize
number
default:"100"
Hard cap on limit query parameter. Requests above this value are clamped.
trackInventory
boolean
default:"true"
Enable inventory tracking by default for new products. Products with trackInventory: false skip all inventory increment and decrement operations.

Store endpoints

Store endpoints are public and return only active products. Use these in your storefront to browse, search, and display products.

Products

MethodPathDescription
GET/productsList active products, paginated and filterable
GET/products/featuredGet featured products
GET/products/:slugGet a single product by slug, including variants
GET/products/search?q=Search products by name, description, or tags
GET/products/store-searchFull-text product search
GET/products/related/:idGet related products scored by category and shared tags
Query parameters for GET /products
ParamTypeDescription
pagenumberPage number (default 1)
limitnumberItems per page, capped at maxPageSize
categorystringFilter by category slug
statusstringProduct status. The storefront always filters to active.
featuredbooleanFilter to featured products only

Categories

MethodPathDescription
GET/categoriesList visible categories
GET/categories/:slugGet a single category by slug

Collections

MethodPathDescription
GET/collectionsList visible collections
GET/collections/:slugGet a collection with its active products

Admin endpoints

Admin endpoints require authentication and return all product statuses (draft, active, archived).

Products

MethodPathDescription
POST/admin/productsCreate a new product
GET/admin/products/listList all products across all statuses
GET/admin/products/:idGet a product by ID
PUT/admin/products/:idUpdate a product
DELETE/admin/products/:idDelete a product (cascades to variants)
POST/admin/products/bulk-actionBulk update status or bulk delete
POST/admin/products/importImport products from CSV data

Variants

MethodPathDescription
POST/admin/products/:productId/variantsAdd a variant to a product
PUT/admin/variants/:idUpdate a variant
DELETE/admin/variants/:idDelete a variant

Categories

MethodPathDescription
POST/admin/categoriesCreate a category
GET/admin/categories/listList all categories
PUT/admin/categories/:idUpdate a category
DELETE/admin/categories/:idDelete a category

Collections

MethodPathDescription
POST/admin/collectionsCreate a collection
GET/admin/collections/listList all collections
PUT/admin/collections/:idUpdate a collection
DELETE/admin/collections/:idDelete a collection (cascades to product links)
POST/admin/collections/:id/productsAdd a product to a collection
DELETE/admin/collections/:id/products/:productIdRemove a product from a collection

Components

Add these components to your MDX template files. The module must be listed in config.json for the components to be available.

ProductCard

Displays a single product card with image, name, price, discount badge, and an optional Add to Cart button.
product
Product
required
A Product object. See the Types section for the full shape.
showAddToCart
boolean
default:"true"
Show the Add to Cart button on the card.
<ProductCard product={product} />

<ProductCard product={product} showAddToCart={false} />

FeaturedProducts

Responsive grid of featured products. Fetches its own data; no props required.
limit
number
Maximum number of featured products to display.
title
string
Section heading rendered above the grid.
<FeaturedProducts />

<FeaturedProducts limit={4} title="Staff Picks" />

ProductListing

Full product listing with search, category, price, stock, and tag filters, plus sorting and pagination. Fetches its own data.
initialCategory
string
Pre-select a category filter on initial render.
Pre-fill the search query on initial render.
pageSize
number
Number of products per page.
<ProductListing />

<ProductListing initialCategory="shoes" pageSize={12} />

ProductDetail

Full product detail page including image gallery, variant selector, pricing, inventory status, reviews, and related products. Loaded automatically by the store’s /products/:slug catch-all route.
slug
string
required
Product slug from the URL.
params
Record<string, string>
required
Route params object (for example params.slug).

RelatedProducts

Horizontal grid of related products scored by shared category and tags. Fetches its own data.
productId
string
required
Product ID to find related products for.
limit
number
Maximum number of related products to show.
title
string
Section heading.
<RelatedProducts productId={product.id} />

<RelatedProducts productId={product.id} limit={4} title="You may also like" />

CollectionCard

Displays a single collection card with image, name, and description.
collection
CollectionCardData
required
Collection object with id, name, slug, description, and image.
<CollectionCard collection={collection} />

CollectionGrid

Grid of collections with optional featured-only filtering. Fetches its own data.
title
string
Section heading.
When true, only featured collections are shown.
<CollectionGrid />

<CollectionGrid title="Shop by Category" featured={true} />

CollectionDetail

Full collection page with image, description, product count, and products grid. Loaded automatically by the store’s /collections/:slug catch-all route.
slug
string
required
Collection slug from the URL.
params
Record<string, string>
required
Route params object.

StarDisplay

Read-only star rating display.
rating
number
required
Rating value between 0 and 5.
size
"sm" | "md" | "lg"
default:"\"md\""
Star size.
<StarDisplay rating={4.5} />

<StarDisplay rating={product.averageRating} size="sm" />

StarPicker

Interactive star rating input for review submission.
value
number
required
Current rating value.
onChange
(n: number) => void
required
Callback fired when the user selects a rating.
<StarPicker value={rating} onChange={setRating} />

StockBadge

Inventory status badge. Displays “Out of stock”, “Only X left”, or “In stock” based on the inventory count.
inventory
number
required
Available inventory count.
<StockBadge inventory={product.inventory} />

ProductReviewsSection

Complete review section with rating summary, paginated review list, and a review submission form. Fetches its own data.
productId
string
required
Product ID to show reviews for.
<ProductReviewsSection productId={product.id} />

Types

interface Product {
  id: string;
  name: string;
  slug: string;
  description?: string;
  shortDescription?: string;
  price: number;               // in cents
  compareAtPrice?: number;     // in cents
  costPrice?: number;          // in cents
  sku?: string;
  barcode?: string;
  inventory: number;
  trackInventory: boolean;
  allowBackorder: boolean;
  status: "draft" | "active" | "archived";
  categoryId?: string;
  images: string[];
  tags: string[];
  isFeatured: boolean;
  weight?: number;
  weightUnit?: "kg" | "lb" | "oz" | "g";
  metadata?: Record<string, unknown>;
  createdAt: Date;
  updatedAt: Date;
}

interface ProductVariant {
  id: string;
  productId: string;
  name: string;
  sku?: string;
  price: number;               // in cents
  compareAtPrice?: number;     // in cents
  costPrice?: number;          // in cents
  inventory: number;
  options: Record<string, string>; // e.g. { size: "M", color: "Blue" }
  images: string[];
  position: number;
  weight?: number;
  weightUnit?: "kg" | "lb" | "oz" | "g";
  createdAt: Date;
  updatedAt: Date;
}

interface Category {
  id: string;
  name: string;
  slug: string;
  description?: string;
  parentId?: string;           // Self-referential for nested categories
  image?: string;
  position: number;
  isVisible: boolean;
  metadata?: Record<string, unknown>;
  createdAt: Date;
  updatedAt: Date;
}

interface ProductWithVariants extends Product {
  variants: ProductVariant[];
  category?: Category;
}
All price fields (price, compareAtPrice, costPrice) are stored and returned in cents. Divide by 100 to display a dollar amount. When importing products from CSV, the import pipeline converts dollar values to cents automatically.

Notes

  • Store endpoints always filter to status: "active". Admin endpoints return all statuses.
  • Deleting a category orphans its child categories and products rather than cascading; categoryId and parentId are set to undefined.
  • Deleting a product cascades to all its variants. Deleting a collection cascades to collection-product links.
  • addProductToCollection is idempotent. Adding a product already in a collection returns the existing link.
  • Inventory decrement has no floor and can go negative. Products with trackInventory: false skip all inventory operations.
  • Related products are scored by shared category (+10 points) and shared tags (+1 point each).