[object Object]

← back to Dw Domain Fleet

Per-site catalog extras overlay (data/extras/<slug>.json) — site-exclusive products w/ buy_url, no flagship-store write, survives pull-catalog. For asseeninla LA-toile line.

7c6386c8882cdcbe29aac3e24029a65a579905a6 · 2026-06-01 15:33:14 -0700 · Steve Abrams

Files touched

Diff

commit 7c6386c8882cdcbe29aac3e24029a65a579905a6
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Mon Jun 1 15:33:14 2026 -0700

    Per-site catalog extras overlay (data/extras/<slug>.json) — site-exclusive products w/ buy_url, no flagship-store write, survives pull-catalog. For asseeninla LA-toile line.
---
 server.js         |  7 +++++++
 shared/catalog.js | 18 +++++++++++++++++-
 2 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/server.js b/server.js
index 8c8e13d..1cd8fc5 100644
--- a/server.js
+++ b/server.js
@@ -36,6 +36,10 @@ const NICHE = catalog.nicheSlice({
 // fallback: if a niche is too thin, broaden to all clean wallcoverings
 const POOL = NICHE.length >= 24 ? NICHE
   : catalog.nicheSlice({ pos: [], neg: cfg.niche.neg || [], types: ['Wallcovering'], limit: 6000 });
+// Per-site catalog overlay (data/extras/<slug>.json) — site-exclusive products
+// prepended so they read as newest. No-op for sites without an extras file.
+const EXTRAS = catalog.siteExtras(SITE);
+if (EXTRAS.length) { POOL.unshift(...EXTRAS); console.log(`[${SITE}] + ${EXTRAS.length} site extras`); }
 console.log(`[${SITE}] niche pool: ${NICHE.length} (serving ${POOL.length})`);
 
 // Hero images come from the precomputed global allocation manifest, which
@@ -127,6 +131,9 @@ app.get('/buy/:slug', (req, res) => {
   const p = POOL.find(x => render.productSlug(x) === key)
          || POOL.find(x => x.handle === key);
   if (!p || !p.handle) return res.status(404).type('html').send(render.aboutPage(cfg));
+  // Site-extras (AI-generated, not on the DW Shopify store) carry their own
+  // sample CTA target so the buy link never 404s on the main store.
+  if (p.buy_url) return res.redirect(302, p.buy_url);
   res.redirect(302, 'https://designerwallcoverings.com/products/'
     + encodeURIComponent(p.handle) + '#sample');
 });
diff --git a/shared/catalog.js b/shared/catalog.js
index 99ef6b3..82cc25c 100644
--- a/shared/catalog.js
+++ b/shared/catalog.js
@@ -59,4 +59,20 @@ function nicheSlice({ pos = [], neg = [], types = [], limit = 4000 }) {
   return out;
 }
 
-module.exports = { RAW, CLEAN, isJunk, normType, nicheSlice, count: CLEAN.length };
+/**
+ * siteExtras — per-site catalog overlay. Returns the products in
+ * data/extras/<slug>.json (or [] if none). Used to add site-exclusive products
+ * (e.g. the AI-generated LA toile line on asseeninla) WITHOUT writing to the
+ * shared Shopify feed and WITHOUT being clobbered by pull-catalog. Each extra is
+ * a normal product object (title, handle, image_url, sku, product_type, tags,
+ * price, created_at) and may carry an optional buy_url for the sample CTA.
+ */
+function siteExtras(slug) {
+  if (!slug) return [];
+  try {
+    const d = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'data', 'extras', slug + '.json'), 'utf8'));
+    return Array.isArray(d) ? d.filter(p => p && p.image_url && p.handle) : [];
+  } catch { return []; }
+}
+
+module.exports = { RAW, CLEAN, isJunk, normType, nicheSlice, siteExtras, count: CLEAN.length };

← 251f908 fleet-heroes: fix spurious exit-1 in deploy mode + dedup by  ·  back to Dw Domain Fleet  ·  Vendor-neutral image proxy: render emits /img/<token>, serve bd7303f →