← back to Wallco Ai
universal search: match designs by color name (blue/navy/teal/cream/sage…) derived from dominant_hex via lib/color _hueBucket+hueName — was title/category/motif only, so color queries returned 0 (blue 0→271, green 0→435, teal 0→253). Cached per hex; text searches unchanged
e25598a6b68ecf3253e80cec849f47cd3dfcc716 · 2026-06-03 14:34:35 -0700 · Steve Abrams
Files touched
Diff
commit e25598a6b68ecf3253e80cec849f47cd3dfcc716
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Wed Jun 3 14:34:35 2026 -0700
universal search: match designs by color name (blue/navy/teal/cream/sage…) derived from dominant_hex via lib/color _hueBucket+hueName — was title/category/motif only, so color queries returned 0 (blue 0→271, green 0→435, teal 0→253). Cached per hex; text searches unchanged
---
server.js | 42 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 42 insertions(+)
diff --git a/server.js b/server.js
index 77e9c38..bf409a0 100644
--- a/server.js
+++ b/server.js
@@ -776,6 +776,46 @@ const UNIVERSAL_PAGES = [
// and navigable pages (matched by title + keyword aliases). Pure read-only,
// in-memory — no DB. Falls back to a did-you-mean over the motif/category
// vocabulary when nothing matched, and to a browse payload when q is empty.
+// Map a design's dominant_hex → the color WORDS a shopper would type ("blue",
+// "navy", "cream"…), so the universal search can match by color, not just by
+// title/category/motif. Reuses lib/color helpers (pure math, no API). Cached by
+// hex since the same colors recur across the catalog. (2026-06-03 — closes the
+// "blue / teal / green → 0 results" search gap.)
+const _colorTokCache = new Map();
+function colorTokensForHex(hex) {
+ if (!hex) return [];
+ const key = String(hex).toLowerCase();
+ const hit = _colorTokCache.get(key);
+ if (hit) return hit;
+ const toks = new Set();
+ const bucket = _hueBucket(hex); // 'blue','green','neutral',…
+ const name = (hueName(hex) || '').toLowerCase(); // 'sapphire','sage',…
+ if (name) toks.add(name);
+ const hsl = _hexToHsl(hex) || { h: 0, s: 0, l: 50 };
+ if (bucket === 'neutral') {
+ toks.add('neutral');
+ if (hsl.l >= 78) ['cream', 'ivory', 'white', 'beige', 'bone'].forEach(t => toks.add(t));
+ else if (hsl.l <= 22) ['charcoal', 'black'].forEach(t => toks.add(t));
+ else ['gray', 'grey', 'taupe', 'greige'].forEach(t => toks.add(t));
+ } else {
+ toks.add(bucket);
+ const SYN = {
+ red: ['red', 'crimson', 'scarlet'], orange: ['orange', 'terracotta', 'rust'],
+ yellow: ['yellow', 'gold', 'honey', 'amber'], chartreuse: ['chartreuse', 'lime', 'green'],
+ green: ['green', 'emerald', 'olive', 'sage'], teal: ['teal', 'turquoise', 'aqua'],
+ cyan: ['cyan', 'aqua', 'turquoise', 'blue'], blue: ['blue', 'navy', 'azure', 'cobalt'],
+ indigo: ['indigo', 'blue', 'violet'], violet: ['violet', 'purple', 'plum', 'mauve', 'lavender'],
+ magenta: ['magenta', 'pink', 'fuchsia', 'rose'],
+ };
+ (SYN[bucket] || []).forEach(t => toks.add(t));
+ if (hsl.l <= 28) toks.add('dark');
+ if (hsl.l >= 72) toks.add('light');
+ }
+ const arr = Array.from(toks);
+ _colorTokCache.set(key, arr);
+ return arr;
+}
+
// Used by both GET /api/search (JSON) and GET /search (server-rendered page).
function universalSearch(qRaw, limit) {
qRaw = String(qRaw || '').toLowerCase().trim();
@@ -842,6 +882,7 @@ function universalSearch(qRaw, limit) {
const category = (d.category || '').toLowerCase();
const handle = (d.handle || '').toLowerCase();
const motifs = (d.motifs || []).map(m => String(m).toLowerCase());
+ const ctoks = colorTokensForHex(d.dominant_hex); // color WORDS for this design
let score = 0;
for (const t of terms) {
if (motifs.some(m => m === t)) score += 5;
@@ -850,6 +891,7 @@ function universalSearch(qRaw, limit) {
if (category === t) score += 2;
else if (category.includes(t)) score += 1;
if (handle.includes(t)) score += 1;
+ if (ctoks.includes(t)) score += 2; // color-name match (blue/navy/cream…)
}
if (score > 0) {
designs.push({
← 4cb93d5 admin: /admin/mural-masters local review gallery for room-si
·
back to Wallco Ai
·
YOLO ledger: 2026-06-03 EVE run — DTD verdict B + T1 color-n 3c40e9c →