diff --git a/app/page.tsx b/app/page.tsx
index 97de2d8..71226ca 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -3,6 +3,8 @@
import Link from 'next/link';
import { useEffect, useState } from 'react';
import FadeImage from '@/components/FadeImage';
+import VariantChips from '@/components/VariantChips';
+import { countDistinctProducts, dedupeVariantGroups, variantDisplayName } from '@/lib/variants';
export default function Home() {
const [design, setDesign] = useState
(null);
@@ -33,7 +35,7 @@ export default function Home() {
products.push(product);
});
});
- setAllProducts(products);
+ setAllProducts(dedupeVariantGroups(products));
try {
const inventoryResponse = await fetch('/api/inventory');
@@ -215,7 +217,7 @@ export default function Home() {
@@ -231,8 +233,9 @@ export default function Home() {
className="font-bold text-lg mb-1"
style={{ color: design.colors.primary, fontFamily: design.fonts.titleFont }}
>
- {product.name}
+ {variantDisplayName(product)}
+
SKU: {product.sku}
@@ -299,8 +302,8 @@ export default function Home() {
fontFamily: design.fonts.bodyFont,
}}
>
- {collection.products.length}{' '}
- {collection.products.length === 1 ? 'product' : 'products'}
+ {countDistinctProducts(collection.products)}{' '}
+ {countDistinctProducts(collection.products) === 1 ? 'product' : 'products'}
@@ -181,8 +183,9 @@ export default function ShopAllPage() {
fontFamily: design.fonts.titleFont,
}}
>
- {product.name}
+ {variantDisplayName(product)}
+
;
+}): ReactElement | null {
+ if (!product.variants || product.variants.length === 0) return null;
+ const seen = new Set();
+ const uniqueValues = product.variants
+ .map((v) => v.values[0])
+ .filter((val) => val && !seen.has(val) && !!seen.add(val));
+
+ return (
+
+
+ {product.variantDimensions?.[0] ?? 'Options'}:
+
+
+ {uniqueValues.map((value) => {
+ const withValue = product.variants!.filter((v) => v.values[0] === value);
+ const allOOS = withValue.length > 0 && withValue.every(
+ (v) => stockMap[v.id] !== undefined && stockMap[v.id] <= 0
+ );
+ const isActive = product.variantValues?.[0] === value;
+ return (
+
+ {value}
+
+ );
+ })}
+
+
+ );
+}
diff --git a/lib/variants.ts b/lib/variants.ts
new file mode 100644
index 0000000..28cd5d3
--- /dev/null
+++ b/lib/variants.ts
@@ -0,0 +1,31 @@
+// lib/variants.ts — Variant grouping helpers (STS-3.0.0+)
+//
+// A "variant group" is 2+ sibling products that share a base name (e.g. the same
+// product in several sizes or colors). The catalog engine stamps a `variants`
+// array onto every member of a group. These helpers collapse a group down to a
+// single representative product so that product LISTINGS and product COUNTS treat
+// one variant set as one item (instead of one per size/color).
+
+export interface VariantLike {
+ id: string;
+ variants?: { id: string }[];
+}
+
+// Returns one representative per variant group (the first variant in the group),
+// leaving non-variant products untouched. Input order is preserved.
+export function dedupeVariantGroups(products: T[]): T[] {
+ return products.filter(
+ (p) => !p.variants || p.variants.length === 0 || p.variants[0].id === p.id
+ );
+}
+
+// Count of distinct products, treating each variant group as a single item.
+export function countDistinctProducts(products: VariantLike[]): number {
+ return dedupeVariantGroups(products).length;
+}
+
+// Display name for a card: the variant group base name (e.g. "Branded Sneakers")
+// rather than the folder name of one variant ("Branded Sneakers (10)").
+export function variantDisplayName(product: { name: string; variantGroup?: string }): string {
+ return product.variantGroup || product.name;
+}
diff --git a/lib/version.ts b/lib/version.ts
index 5e70c77..3cfb870 100644
--- a/lib/version.ts
+++ b/lib/version.ts
@@ -36,7 +36,7 @@
* 4. Commit with version number in commit message
*/
-export const VERSION = 'STS-2.6.3';
+export const VERSION = 'STS-3.0.1';
export const VERSION_INFO = {
name: 'Shop Template System',
diff --git a/package.json b/package.json
index c370421..e160e27 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "shop-template-system",
- "version": "3.0.0",
+ "version": "3.0.1",
"private": true,
"scripts": {
"dev": "next dev",