[object Object]

← back to Wallco Ai

homepage hero: prefer photoreal room-mockup over flat tile when available (heroImageUrl helper picks /designs/room/design_<id>_<room>.png if room_mockups[] non-empty); heroDesigns() biases toward rooms-first, falls back to high-sat flat tiles to fill 6 slides

46eb2943b761cbe36f151a02d1961e58051c8a7e · 2026-05-28 11:05:33 -0700 · Steve Abrams

Files touched

Diff

commit 46eb2943b761cbe36f151a02d1961e58051c8a7e
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Thu May 28 11:05:33 2026 -0700

    homepage hero: prefer photoreal room-mockup over flat tile when available (heroImageUrl helper picks /designs/room/design_<id>_<room>.png if room_mockups[] non-empty); heroDesigns() biases toward rooms-first, falls back to high-sat flat tiles to fill 6 slides
---
 server.js | 31 ++++++++++++++++++++++++-------
 1 file changed, 24 insertions(+), 7 deletions(-)

diff --git a/server.js b/server.js
index e270c44..e0315ce 100644
--- a/server.js
+++ b/server.js
@@ -4708,12 +4708,29 @@ const HAMBURGER_JS = `
 </script>`;
 
 // ── Hero rotation images (highest-saturation designs, sat > 0.4)
+// Map a design row to the URL we want in the hero slot. Prefer a photoreal
+// room-mockup over the flat tile when available — Steve directive 2026-05-28
+// "use room settings for hero images". Room files served by the static route
+// at /designs/room/ from data/rooms/design_<id>_<room>.png. Falls back to the
+// flat tile (d.image_url) for designs with no rooms yet.
+function heroImageUrl(d) {
+  if (Array.isArray(d.room_mockups) && d.room_mockups.length) {
+    return '/designs/room/design_' + d.id + '_' + d.room_mockups[0] + '.png';
+  }
+  return d.image_url;
+}
 function heroDesigns() {
-  const h = DESIGNS
-    .filter(d => d.saturation > 0.3)
-    .sort((a,b) => b.saturation - a.saturation);
-  // fallback: if none qualify, use all sorted by saturation
-  return h.length >= 2 ? h : [...DESIGNS].sort((a,b) => b.saturation - a.saturation);
+  // Prefer designs with a photoreal room AND solid saturation. Fall back to
+  // any rooms, then to high-sat flat tiles, so the page never blanks out.
+  const withRooms = DESIGNS.filter(d => Array.isArray(d.room_mockups) && d.room_mockups.length);
+  if (withRooms.length >= 6) {
+    return withRooms.sort((a,b) => (b.saturation || 0) - (a.saturation || 0));
+  }
+  // Mix mode: pad the rooms set with high-sat flat tiles so we still hit ≥6 slides
+  const flatHi = DESIGNS.filter(d => d.saturation > 0.3 && !(Array.isArray(d.room_mockups) && d.room_mockups.length))
+                        .sort((a,b) => b.saturation - a.saturation);
+  const mixed = [...withRooms, ...flatHi];
+  return mixed.length >= 2 ? mixed : [...DESIGNS].sort((a,b) => b.saturation - a.saturation);
 }
 
 // ── HOME PAGE
@@ -4777,7 +4794,7 @@ app.get('/', (req, res) => {
   });
 
   const heroSlides = heroes.slice(0, 6).map((d, i) =>
-    `<div class="hero-slide ${i===0?'active':''}" data-idx="${i}" style="background-image:url('${d.image_url}');--card-bg:url('${d.image_url}')" aria-label="${d.title}"></div>`
+    `<div class="hero-slide ${i===0?'active':''}" data-idx="${i}" style="background-image:url('${heroImageUrl(d)}');--card-bg:url('${heroImageUrl(d)}')" aria-label="${d.title}"></div>`
   ).join('\n');
 
   // Top categories by count — used to render the home random-rail chip strip.
@@ -4833,7 +4850,7 @@ app.get('/', (req, res) => {
     // fetching during <head> parse instead of after body scan discovers the
     // background-image URLs. heroes[0] is the most likely LCP candidate.
     preloadImages: [
-      heroes[0]?.image_url,
+      heroes[0] && heroImageUrl(heroes[0]),
       ...featured.slice(0, 4).map(d => d.image_url)
     ].filter(Boolean)
   })}

← f538318 /design/:id 'Sell on Etsy' button — go one-click force-add b  ·  back to Wallco Ai  ·  /designs grid bulk-action: scrub URL creds on fetch — same f 223088a →