[object Object]

← back to All Designerwallcoverings

all.dw: split 'Catalog only' out of 'Staged' lifecycle + fix status-facet double-count

c78be5a11b3a098f1419a15691a598b3057be398 · 2026-08-24 09:07:04 -0700 · Steve Abrams

- deriveMicrositeRow: never-on-Shopify *_catalog staging rows now read
  'Catalog only' instead of 'Staged', so 'Staged' means only real Shopify
  DRAFT / unpublished-ACTIVE go-live candidates (148,534 -> 42,854 local).
- LIFE_ORDER: add 'Catalog only' chip.
- /api/facets: status facet was passing {skip:'lifecycle'} (should be
  {skip:'status'}); status facet now reconciles to total (314,254 -> 214,358).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Files touched

Diff

commit c78be5a11b3a098f1419a15691a598b3057be398
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Mon Aug 24 09:07:04 2026 -0700

    all.dw: split 'Catalog only' out of 'Staged' lifecycle + fix status-facet double-count
    
    - deriveMicrositeRow: never-on-Shopify *_catalog staging rows now read
      'Catalog only' instead of 'Staged', so 'Staged' means only real Shopify
      DRAFT / unpublished-ACTIVE go-live candidates (148,534 -> 42,854 local).
    - LIFE_ORDER: add 'Catalog only' chip.
    - /api/facets: status facet was passing {skip:'lifecycle'} (should be
      {skip:'status'}); status facet now reconciles to total (314,254 -> 214,358).
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
 server.js | 19 ++++++++++++-------
 1 file changed, 12 insertions(+), 7 deletions(-)

diff --git a/server.js b/server.js
index a82f0a3..7475243 100644
--- a/server.js
+++ b/server.js
@@ -47,10 +47,13 @@ const PRICE_BANDS = [
 const PRICE_ORDER = PRICE_BANDS.map((b) => b.key);
 
 // Lifecycle Steve lists on this surface, ordered live → not-yet-live → internal-only → gone.
-// 'Internal' = deliberately never front-facing (permanent), distinct from 'Staged' (a candidate
-// to go live). Internal lines STAY on this internal grid + facets; they are excluded only from
-// the genuinely front-facing paths (public storefront URL + Google feed) — see isInternalRow.
-const LIFE_ORDER = ['Active on site', 'Staged', 'Internal', 'Archived'];
+// 'Internal' = deliberately never front-facing (permanent), distinct from 'Staged' (a real
+// Shopify DRAFT / unpublished-ACTIVE candidate to go live) and 'Catalog only' (a vendor *_catalog
+// staging row that was never pushed to Shopify at all — see deriveMicrositeRow). Keeping the two
+// apart stops "Staged" from conflating never-on-Shopify catalog rows with real go-live candidates.
+// Internal lines STAY on this internal grid + facets; they are excluded only from the genuinely
+// front-facing paths (public storefront URL + Google feed) — see isInternalRow.
+const LIFE_ORDER = ['Active on site', 'Staged', 'Catalog only', 'Internal', 'Archived'];
 const priceBand = (p) => { if (!p || p <= 0) return null; const b = PRICE_BANDS.find((x) => x.test(p)); return b ? b.key : null; };
 
 const titleCase = (s) => s.replace(/\w\S*/g, (t) => t[0].toUpperCase() + t.slice(1));
@@ -618,8 +621,10 @@ function deriveMicrositeRow(p, feed) {
     fm_name: null, fm_width: null, fm_specs: null, fm_handle: null, mfr_mismatch: false,
     status: 'STAGED',
     // The 4 microsite lines (Fromental/Gracie/Zuber/Crezana) ARE the internal registry vendors,
-    // so they read 'Internal' when registered (never front-facing), else fall back to 'Staged'.
-    lifecycle: isInternalRow({ vendor: feed.vendor }) ? 'Internal' : 'Staged',
+    // so they read 'Internal' when registered (never front-facing). Everything else here is a
+    // *_catalog staging row that was NEVER on Shopify, so it reads 'Catalog only' — NOT 'Staged'
+    // (which is reserved for real Shopify DRAFT / unpublished-ACTIVE go-live candidates, deriveRow).
+    lifecycle: isInternalRow({ vendor: feed.vendor }) ? 'Internal' : 'Catalog only',
     image: primaryImg,
     images,
     image_count: images.length,
@@ -1596,7 +1601,7 @@ const server = http.createServer((req, res) => {
       type: tally(applyFilters(ROWS, f, { skip: 'type' }), 'type'),
       series: tally(applyFilters(ROWS, f, { skip: 'series' }), 'series'),
       lifecycle: tally(applyFilters(ROWS, f, { skip: 'lifecycle' }), 'lifecycle'),
-      status: tally(applyFilters(ROWS, f, { skip: 'lifecycle' }), 'status'),
+      status: tally(applyFilters(ROWS, f, { skip: 'status' }), 'status'),
       color: tallyArr(applyFilters(ROWS, f, { skip: 'color' }), 'colors'),
       style: tallyArr(applyFilters(ROWS, f, { skip: 'style' }), 'styles'),
       material: tallyArr(applyFilters(ROWS, f, { skip: 'material' }), 'materials'),

← 3446057 auto-data-snapshot: 2026-08-20T13:34:43 (1 data files) — pac  ·  back to All Designerwallcoverings  ·  chore: version bump v1.7.2 (session close) f0c0681 →