[object Object]

← back to Wallco Ai

wallco.ai · /designs "In a room ·N" filter chip — surface room-preview designs

354cb1741953321daff788ae776163e32e910f62 · 2026-05-12 00:07:14 -0700 · SteveStudio2

The hover-preview ships only on the top-5 saturated designs today. The
catalog renders 228 total, so a visitor on page 1 might never see one.

Adds a "Preview" filter row right under Motif chips with a single "In a room"
pill. Clicking it appends ?room=1 to the URL and narrows to only designs
that have a residential mockup. The pill shows live count (·5 today, will
grow as more rooms are generated).

Reversible: 1 new query param `room`, 1 new chip row, no schema changes.
Smoke: ?room=1 returns 5 cards (vs 228 default); all 5 carry the has-room
class so the hover overlay fires on the first card the visitor sees.

Files touched

Diff

commit 354cb1741953321daff788ae776163e32e910f62
Author: SteveStudio2 <stevestudio2@SteveStacStudio.lan>
Date:   Tue May 12 00:07:14 2026 -0700

    wallco.ai · /designs "In a room ·N" filter chip — surface room-preview designs
    
    The hover-preview ships only on the top-5 saturated designs today. The
    catalog renders 228 total, so a visitor on page 1 might never see one.
    
    Adds a "Preview" filter row right under Motif chips with a single "In a room"
    pill. Clicking it appends ?room=1 to the URL and narrows to only designs
    that have a residential mockup. The pill shows live count (·5 today, will
    grow as more rooms are generated).
    
    Reversible: 1 new query param `room`, 1 new chip row, no schema changes.
    Smoke: ?room=1 returns 5 cards (vs 228 default); all 5 carry the has-room
    class so the hover overlay fires on the first card the visitor sees.
---
 server.js | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/server.js b/server.js
index 35a1d72..6d93810 100644
--- a/server.js
+++ b/server.js
@@ -824,6 +824,7 @@ app.get('/designs', (req, res) => {
 
   const motifQ = (req.query.motif || '').toLowerCase().trim();
   const hueQ   = (req.query.hue   || '').toLowerCase().trim();
+  const roomQ  = (req.query.room  || '').toLowerCase().trim();  // '1' or 'all' = only designs with room previews
   function hueBucketOf(hex) {
     if (!hex || !/^#[0-9a-fA-F]{6}$/.test(hex)) return null;
     const r = parseInt(hex.slice(1,3),16)/255, g = parseInt(hex.slice(3,5),16)/255, b = parseInt(hex.slice(5,7),16)/255;
@@ -851,6 +852,7 @@ app.get('/designs', (req, res) => {
   if (cat)    filtered = filtered.filter(d => d.category === cat);
   if (motifQ) filtered = filtered.filter(d => (d.motifs || []).includes(motifQ));
   if (hueQ)   filtered = filtered.filter(d => hueBucketOf(d.dominant_hex) === hueQ);
+  if (roomQ)  filtered = filtered.filter(d => (d.room_mockups || []).length > 0);
   if (q)    filtered = filtered.filter(d =>
     d.title.toLowerCase().includes(q) ||
     d.category.toLowerCase().includes(q) ||
@@ -1008,7 +1010,26 @@ ${htmlHeader('/designs')}
       ${topMotifs.map(([m,n]) => `<a href="/designs?${cat?'cat='+encodeURIComponent(cat)+'&':''}motif=${encodeURIComponent(m)}" class="motif-chip${motifQ===m?' is-on':''}" style="font:11px var(--sans);padding:5px 12px;border:1px solid ${motifQ===m?'var(--accent)':'var(--line)'};background:${motifQ===m?'var(--accent)':'transparent'};color:${motifQ===m?'var(--bg)':'var(--ink-soft)'};border-radius:999px;text-decoration:none">${m} <span style="opacity:.55">·${n}</span></a>`).join('')}
     </div>
 
-    <p class="result-count">${total} design${total===1?'':'s'}${cat?' in '+cat:''}${motifQ?' with '+motifQ:''}${q?' matching "'+q+'"':''}</p>
+    <!-- Room-preview filter chip (toggles ?room=1 — shows only designs that have a residential mockup) -->
+    ${(() => {
+      const roomCnt = DESIGNS.filter(d => (d.room_mockups || []).length > 0).length;
+      const on = !!roomQ;
+      const href = `/designs${[
+        cat   ? `cat=${encodeURIComponent(cat)}`     : '',
+        motifQ? `motif=${encodeURIComponent(motifQ)}`: '',
+        hueQ  ? `hue=${encodeURIComponent(hueQ)}`    : '',
+        !on   ? 'room=1'                             : ''
+      ].filter(Boolean).join('&').replace(/^/, on ? '' : '?')}`;
+      return `<div class="motif-chips" style="display:flex;flex-wrap:wrap;gap:6px;margin:0 0 6px;align-items:center">
+        <span style="font:11px var(--sans);text-transform:uppercase;letter-spacing:.08em;color:var(--ink-faint);margin-right:6px">Preview</span>
+        <a href="${href}" class="motif-chip${on?' is-on':''}" title="Show only designs with a room mockup preview"
+           style="font:11px var(--sans);padding:5px 12px;border:1px solid ${on?'var(--accent)':'var(--line)'};background:${on?'var(--accent)':'transparent'};color:${on?'var(--bg)':'var(--ink-soft)'};border-radius:999px;text-decoration:none">
+          In a room <span style="opacity:.55">·${roomCnt}</span>
+        </a>
+      </div>`;
+    })()}
+
+    <p class="result-count">${total} design${total===1?'':'s'}${cat?' in '+cat:''}${motifQ?' with '+motifQ:''}${roomQ?' with room preview':''}${q?' matching "'+q+'"':''}</p>
 
     <div id="surprise-result" style="display:none;margin-bottom:18px;padding:16px;border:1px solid var(--gold);border-radius:8px;background:var(--card-bg)"></div>
     <script>

← a7922f0 hot-or-not: standalone server on port 9794 — own pm2 process  ·  back to Wallco Ai  ·  wallco.ai · refinement signal: ctx-passing through /swipe + c6eb465 →