← back to Vinylwallpaper
rails: build from tags via shared rail-match helper (fix degenerate single-rail collapse)
66ff058a7a004b8dec7d98ac31b7f6dc731c4a00 · 2026-05-26 10:18:02 -0700 · Steve Abrams
Files touched
M server.jsM site.config.json
Diff
commit 66ff058a7a004b8dec7d98ac31b7f6dc731c4a00
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Tue May 26 10:18:02 2026 -0700
rails: build from tags via shared rail-match helper (fix degenerate single-rail collapse)
---
server.js | 24 ++++++++++++++++--------
site.config.json | 12 ++++++------
2 files changed, 22 insertions(+), 14 deletions(-)
diff --git a/server.js b/server.js
index ab3eccb..a034902 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 : [];
@@ -196,12 +197,19 @@ app.get('/api/products', (req, res) => {
});
app.get('/api/sliders', (req, res) => {
- const out = [];
- for (const a of SITE_RAILS) {
- const items = PRODUCTS_NICHE.filter(p => p.aesthetic === a).slice(0, 12);
- if (items.length >= 4) out.push({ aesthetic: a, items });
- }
- res.json({ rails: out });
+ const RAIL_LABELS = {
+ 'textured': 'Textured Surfaces',
+ 'contemporary': 'Contemporary',
+ 'beige': 'Neutral & Beige',
+ 'minimalist': 'Minimalist',
+ 'traditional': 'Traditional',
+ 'geometric': 'Geometric',
+ };
+ const rails = buildRails(PRODUCTS_NICHE, SITE_RAILS).map(r => ({
+ ...r,
+ label: RAIL_LABELS[r.key] || r.key,
+ }));
+ res.json({ rails });
});
app.get('/api/facets', (req, res) => {
@@ -214,9 +222,9 @@ app.get('/api/facets', (req, res) => {
list = list.filter(p => (p.title || '').toLowerCase().includes(needle) || (p.tags || []).some(t => String(t).toLowerCase().includes(needle)));
}
if (aesthetic && aesthetic !== 'all') list = list.filter(p => p.aesthetic === aesthetic);
- 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 baeefac..d7fb430 100644
--- a/site.config.json
+++ b/site.config.json
@@ -10,11 +10,11 @@
"accent": "#5a6a8a"
},
"rails": [
- "type-ii",
- "commercial",
- "hospitality",
- "healthcare",
- "contract",
- "wipe-clean"
+ "textured",
+ "contemporary",
+ "beige",
+ "minimalist",
+ "traditional",
+ "geometric"
]
}
← 15e301a rails: editorial labels for firing aesthetic buckets
·
back to Vinylwallpaper
·
rails: editorial labels for new tag-derived rail keys (index b4b5619 →