[object Object]

← back to Silkwallcoverings

rails: tag-aware via shared rail-match helper + editorial LABELS (fix degenerate single-rail)

1ec7c63441a08b7b9fc768a04a98c90553d8935b · 2026-05-26 10:27:00 -0700 · Steve Abrams

Files touched

Diff

commit 1ec7c63441a08b7b9fc768a04a98c90553d8935b
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Tue May 26 10:27:00 2026 -0700

    rails: tag-aware via shared rail-match helper + editorial LABELS (fix degenerate single-rail)
---
 public/index.html |  2 +-
 server.js         | 11 +++--------
 site.config.json  |  9 ++++-----
 3 files changed, 8 insertions(+), 14 deletions(-)

diff --git a/public/index.html b/public/index.html
index 8fe8f8f..35e1465 100644
--- a/public/index.html
+++ b/public/index.html
@@ -485,7 +485,7 @@ const HOSTKEY = location.hostname.replace(/\./g, '_');
     document.documentElement.dataset.view = state.view;
   } catch(e){}
 })();
-const LABELS = {"all":"All","durable":"High-Durability Silk","architectural":"Architectural Silk"};
+const LABELS = {"all":"All","durable":"High-Durability Silk","architectural":"Architectural Silk","textured":"Textured Silk","contemporary":"Contemporary","beige":"Neutral Tones","type 2":"Commercial Grade"};
 
 function escAttr(s) { return String(s == null ? '' : s).replace(/[&<>"']/g, c => ({ '&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;' }[c])); }
 // Image-URL allowlist: only DW Shopify CDN + designerwallcoverings.com (defends against XSS via crafted products.json)
diff --git a/server.js b/server.js
index 0ab1746..74ba7f2 100644
--- a/server.js
+++ b/server.js
@@ -19,6 +19,7 @@ if (ADMIN_ENABLED) {
   try { catalog = require('../_shared/admin-catalog'); }
   catch (e) { console.error(`[${__SITE}] admin-catalog unavailable (${e.message}) — falling back to static JSON`); }
 }
+const { buildRails, railFacets } = require('../_shared/rail-match');
 const siteCfg = JSON.parse(fs.readFileSync(path.join(__dirname, 'site.config.json'), 'utf8'));
 const SITE_SLUG = siteCfg.slug || __SITE;
 const SITE_RAILS = Array.isArray(siteCfg.rails) ? siteCfg.rails : [];
@@ -176,12 +177,7 @@ app.get('/api/products', (req, res) => {
 });
 
 app.get('/api/sliders', (req, res) => {
-  const out = [];
-  for (const a of SITE_RAILS) {
-    const items = PRODUCTS.filter(p => p.aesthetic === a).slice(0, 12);
-    if (items.length >= 4) out.push({ aesthetic: a, items });
-  }
-  res.json({ rails: out });
+  res.json({ rails: buildRails(PRODUCTS, SITE_RAILS) });
 });
 
 app.get('/api/facets', (req, res) => {
@@ -193,9 +189,8 @@ app.get('/api/facets', (req, res) => {
   }
   if (aesthetic && aesthetic !== 'all') list = list.filter(p => p.aesthetic === aesthetic);
   if (vendor && vendor !== 'all') list = list.filter(p => p.vendor === vendor);
-  const aesthetics = {}; const vendors = {};
+  const aesthetics = railFacets(list, SITE_RAILS); const vendors = {};
   for (const p of list) {
-    aesthetics[p.aesthetic] = (aesthetics[p.aesthetic] || 0) + 1;
     vendors[p.vendor] = (vendors[p.vendor] || 0) + 1;
   }
   res.json({ aesthetics, vendors, total: list.length });
diff --git a/site.config.json b/site.config.json
index 69a88eb..bfdcee8 100644
--- a/site.config.json
+++ b/site.config.json
@@ -10,11 +10,10 @@
     "accent": "#c8a878"
   },
   "rails": [
-    "durable",
+    "textured",
     "architectural",
-    "vinyl",
-    "faux",
-    "finish",
-    "textured"
+    "contemporary",
+    "beige",
+    "type 2"
   ]
 }

← d886855 rails: editorial labels for firing aesthetic buckets  ·  back to Silkwallcoverings  ·  rails: tag-aware facet filter (productInRail) so rail drill- 9abb9ab →