[object Object]

← back to Philipperomano

add ungated public-safe /api/products feed (cork+wallcovering, vendor forced Phillipe Romano, no price/cost, cork-first) for all.dw microsite crawler

9a406f2a6b9c26be347f6a83445d52f0f907fe06 · 2026-08-10 16:11:43 -0700 · steve

Files touched

Diff

commit 9a406f2a6b9c26be347f6a83445d52f0f907fe06
Author: steve <steve@designerwallcoverings.com>
Date:   Mon Aug 10 16:11:43 2026 -0700

    add ungated public-safe /api/products feed (cork+wallcovering, vendor forced Phillipe Romano, no price/cost, cork-first) for all.dw microsite crawler
---
 server.js | 39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/server.js b/server.js
index 1614c87..445b749 100644
--- a/server.js
+++ b/server.js
@@ -822,6 +822,45 @@ app.get('/p/:handle', (req, res) => {
   }));
 });
 
+// ── Ungated public feed for the all.designerwallcoverings.com microsite crawler ──
+// The fleet aggregator's crawler reads each microsite's /api/products to merge its line
+// into the LIVE microsite directory. It seeds phillipe-romano via its localhost feedBase
+// (config/known-subdomains.json), so this route is what surfaces Phillipe Romano's cork +
+// wallcovering line in the directory. Shape is deliberately DW-family general:
+//   { count, products:[{ title, handle, vendor, type, image, url }] }
+// which the crawler's feedProducts() DW branch (j.products) consumes directly.
+// PUBLIC-SAFE ONLY: title/handle/vendor/type/image/store-url — NEVER price/net/cost, and
+// the vendor is FORCED to "Phillipe Romano" (the customer-facing brand). The real upstream
+// mill "Greenland" (and other private-label mills) must NEVER appear — scrubbed defensively.
+const FEED_BANNED = /greenland|command\s*54|wallquest|chesapeake|nextwall|seabrook|rigo|justin\s*david/i;
+const FEED_ROWS = ENRICHED
+  .filter(p => {
+    const blob = `${p.title || ''} ${p.handle || ''} ${p.product_type || ''}`;
+    return !FEED_BANNED.test(blob);
+  })
+  .map(p => ({
+    title: p.title || '',
+    handle: p.handle || null,
+    vendor: 'Phillipe Romano',          // customer-facing brand — never the upstream mill
+    type: p.product_type || null,
+    image: p.image_url || null,
+    url: p.handle ? `${DW_SHOPIFY}/products/${p.handle}` : `${DW_SHOPIFY}`,
+  }));
+// The aggregator was missing the CORK line specifically (greenland.dw/phillipe-romano-*.dw are
+// gated/dead, so no ungated feed carried it). The crawler samples the first N rows into the merged
+// directory feed, so surface cork FIRST here — otherwise the newest wallcoverings crowd it out of
+// the sample and the cork line stays invisible in the directory. Stable within each group.
+FEED_ROWS.sort((a, b) => {
+  const ac = /cork/i.test(`${a.title} ${a.type}`) ? 0 : 1;
+  const bc = /cork/i.test(`${b.title} ${b.type}`) ? 0 : 1;
+  return ac - bc;
+});
+app.get('/api/products', (req, res) => {
+  const limit = Math.min(parseInt(req.query.limit, 10) || FEED_ROWS.length, FEED_ROWS.length);
+  res.set('Cache-Control', 'public, max-age=600, s-maxage=600');
+  res.json({ count: FEED_ROWS.length, products: FEED_ROWS.slice(0, limit) });
+});
+
 app.get('/health', (_req, res) => res.json({ ok: true, products: ENRICHED.length, types: TYPES }));
 
 // Loopback-only on the local Mac. Set BIND=0.0.0.0 in prod env when needed.

← 42c2e93 GA4: inject gtag (G-8WGHZ5FTV0) into SSR head  ·  back to Philipperomano  ·  TK-10869: PhilRomano sample-add script + rollback (Steve-app b36ef94 →