← back to Ventura Claw Leads
yolo tick 24: home featured grid — photo-priority within tier + render hero per card
e1590f826a02ebb4270344f3b42834df0f95387c · 2026-05-07 00:58:51 -0700 · Steve Abrams
routes/public.js GET /: featured query expanded to SELECT photo_path, plus
new ORDER BY tier within priority that prefers businesses-with-photos to
businesses-without-photos within the same tier:
ORDER BY tier='premier' DESC, tier='standard' DESC,
(photo_path IS NOT NULL) DESC,
RANDOM()
So premier listings still always sort first; standard next; within each
tier the rotation favors visually-richer cards that have a real photo
uploaded. Pure positive incentive to upload (better placement) without
penalizing photo-less listings (they still appear, just lower in the
random pool).
views/public/home.ejs featured grid: same per-card hero treatment as /find
— photo when present, vertical-themed gradient + emoji glyph as fallback.
Featured cards now visually match the directory's card pattern.
46/46 tests still pass. The home page transforms once businesses upload
photos: the gradient placeholders give way to actual interior shots,
storefronts, etc.
Files touched
M routes/public.jsM views/public/home.ejs
Diff
commit e1590f826a02ebb4270344f3b42834df0f95387c
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Thu May 7 00:58:51 2026 -0700
yolo tick 24: home featured grid — photo-priority within tier + render hero per card
routes/public.js GET /: featured query expanded to SELECT photo_path, plus
new ORDER BY tier within priority that prefers businesses-with-photos to
businesses-without-photos within the same tier:
ORDER BY tier='premier' DESC, tier='standard' DESC,
(photo_path IS NOT NULL) DESC,
RANDOM()
So premier listings still always sort first; standard next; within each
tier the rotation favors visually-richer cards that have a real photo
uploaded. Pure positive incentive to upload (better placement) without
penalizing photo-less listings (they still appear, just lower in the
random pool).
views/public/home.ejs featured grid: same per-card hero treatment as /find
— photo when present, vertical-themed gradient + emoji glyph as fallback.
Featured cards now visually match the directory's card pattern.
46/46 tests still pass. The home page transforms once businesses upload
photos: the gradient placeholders give way to actual interior shots,
storefronts, etc.
---
routes/public.js | 6 ++++--
views/public/home.ejs | 15 +++++++++++++--
2 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/routes/public.js b/routes/public.js
index c8d2a1d..4e8646e 100644
--- a/routes/public.js
+++ b/routes/public.js
@@ -17,10 +17,12 @@ router.get('/', async (req, res, next) => {
FROM businesses WHERE status = 'active'
`);
const featured = await db.many(`
- SELECT slug, business_name, vertical, neighborhood, city, headline
+ SELECT slug, business_name, vertical, neighborhood, city, headline, photo_path
FROM businesses
WHERE status = 'active' AND (claim_status IN ('self','claimed') OR tier != 'free')
- ORDER BY tier = 'premier' DESC, tier = 'standard' DESC, RANDOM()
+ ORDER BY tier = 'premier' DESC, tier = 'standard' DESC,
+ (photo_path IS NOT NULL) DESC, -- within tier, photos beat no-photos
+ RANDOM()
LIMIT 9
`);
const verticalCounts = await db.many(`
diff --git a/views/public/home.ejs b/views/public/home.ejs
index e5685dc..f72e818 100644
--- a/views/public/home.ejs
+++ b/views/public/home.ejs
@@ -87,9 +87,20 @@
<section class="find-page">
<h2>Featured this week</h2>
<div class="business-grid">
- <% featured.forEach(function(b){ %>
+ <% featured.forEach(function(b){
+ var vMeta = verticals.find(function(v){return v.key===b.vertical});
+ %>
<a class="business-card" href="/business/<%= b.slug %>">
- <p class="biz-vertical"><%= verticals.find(function(v){return v.key===b.vertical}) ? verticals.find(function(v){return v.key===b.vertical}).label : b.vertical %></p>
+ <% if (b.photo_path) { %>
+ <div class="biz-card-hero biz-card-hero-photo">
+ <img src="<%= b.photo_path %>" alt="<%= b.business_name %>" loading="lazy" decoding="async">
+ </div>
+ <% } else { %>
+ <div class="biz-card-hero vertical-hero-<%= b.vertical %>" aria-hidden="true">
+ <span class="biz-card-glyph"><%= vMeta ? vMeta.icon : '•' %></span>
+ </div>
+ <% } %>
+ <p class="biz-vertical"><%= vMeta ? vMeta.label : b.vertical %></p>
<p class="biz-name"><%= b.business_name %></p>
<p class="biz-loc"><%= [b.neighborhood, b.city, b.state].filter(Boolean).join(' · ') %></p>
<% if (b.headline) { %><p class="biz-headline"><%= b.headline %></p><% } %>
← c73de6a yolo tick 23: og:image + Twitter Card image + 'Share this li
·
back to Ventura Claw Leads
·
yolo tick 25: /find auto-suggest dropdown — debounced AJAX, 870584a →