[object Object]

← back to Wallco Ai

drunk-animals: 'Best of the night' rail on /live

768a775b837da9dcc95c9e18e924d83ece8718a5 · 2026-05-13 03:47:47 -0700 · SteveStudio2

/api/drunk-animals/best?n=3 returns top-N highest-saturation designs.
Live page pins a pink-tinted rail above the stream showing the 3 most
saturated covers with hover-lift, dark gradient overlay, and sat score.
Polls every 2 min.

Smoke-tested: top 3 = Rose Hiccup #2240 (orangutan, 0.75), Plum Carouse
#2156 (orangutan, 0.69), Rose Caprice #1537 (capybara, 0.68).

Files touched

Diff

commit 768a775b837da9dcc95c9e18e924d83ece8718a5
Author: SteveStudio2 <stevestudio2@SteveStacStudio.lan>
Date:   Wed May 13 03:47:47 2026 -0700

    drunk-animals: 'Best of the night' rail on /live
    
    /api/drunk-animals/best?n=3 returns top-N highest-saturation designs.
    Live page pins a pink-tinted rail above the stream showing the 3 most
    saturated covers with hover-lift, dark gradient overlay, and sat score.
    Polls every 2 min.
    
    Smoke-tested: top 3 = Rose Hiccup #2240 (orangutan, 0.75), Plum Carouse
    #2156 (orangutan, 0.69), Rose Caprice #1537 (capybara, 0.68).
---
 server.js | 45 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 45 insertions(+)

diff --git a/server.js b/server.js
index cdacd65..19ae4eb 100644
--- a/server.js
+++ b/server.js
@@ -2214,6 +2214,23 @@ app.get('/api/drunk-animals/feed', (req, res) => {
   res.json({ count: rows.length, total: DESIGNS.filter(d => d.category === 'drunk-animals').length, designs: rows });
 });
 
+// ── /api/drunk-animals/best — highest-saturation N drunk-animal designs.
+// Powers the "Best of the night" rail pinned to the top of /live.
+app.get('/api/drunk-animals/best', (req, res) => {
+  res.setHeader('Cache-Control', 'no-store');
+  const n = Math.min(12, Math.max(1, parseInt(req.query.n || '3', 10)));
+  const best = DESIGNS
+    .filter(d => d.category === 'drunk-animals')
+    .sort((a, b) => (b.saturation || 0) - (a.saturation || 0))
+    .slice(0, n)
+    .map(d => ({
+      id: d.id, title: d.title, image_url: d.image_url,
+      dominant_hex: d.dominant_hex, saturation: d.saturation,
+      motifs: d.motifs || [], url: `/design/${d.id}`,
+    }));
+  res.json({ best });
+});
+
 // ── /api/drunk-animals/stats — derived snapshot for the live viewer's
 // "tonight in numbers" bar. Animals are extracted from motifs[] (when
 // llava tagged them) so the bar reflects what actually rendered, not
@@ -2280,6 +2297,14 @@ header a:hover { border-color:var(--pink); color:var(--pink) }
 .stats-bar .animals { display:flex; gap:6px; flex-wrap:wrap; padding-left:14px }
 .stats-bar .animal-pill { padding:3px 10px; border-radius:999px; background:rgba(255,121,198,.12); color:var(--pink); font-size:11px; white-space:nowrap }
 .stats-bar .animal-pill strong { color:#fff; margin-left:4px; font-weight:600 }
+.best-rail { padding:24px 20px 8px; background:linear-gradient(180deg,rgba(255,121,198,.06),transparent) }
+.best-rail h2 { font-family:'Playfair Display',serif; font-weight:400; font-size:14px; margin:0 0 12px; letter-spacing:.2em; text-transform:uppercase; color:var(--pink) }
+.best-row { display:grid; grid-template-columns:repeat(auto-fit,minmax(280px,1fr)); gap:14px }
+.best-card { aspect-ratio:1/1; background-size:cover; background-position:center; border-radius:14px; position:relative; overflow:hidden; display:block; text-decoration:none; color:inherit; border:1px solid rgba(255,121,198,.25); transition:transform .25s ease, box-shadow .25s ease }
+.best-card:hover { transform:translateY(-3px); box-shadow:0 12px 28px rgba(255,121,198,.25) }
+.best-card .info { position:absolute; left:0; right:0; bottom:0; padding:10px 14px; background:linear-gradient(180deg,transparent,rgba(0,0,0,.7)); font-size:12px }
+.best-card .info .t { font-family:'Playfair Display',serif; font-size:16px; line-height:1.2; margin:0 }
+.best-card .info .id { font-size:10px; opacity:.7; letter-spacing:.08em; margin-top:2px }
 main { padding:20px; max-width:1500px; margin:0 auto }
 .grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(280px,1fr)); gap:18px }
 .card { background:#1a0f1a; border:1px solid var(--line); border-radius:14px; overflow:hidden; position:relative; opacity:0; transform:translateY(-12px); animation:slidein .5s ease forwards }
@@ -2310,6 +2335,10 @@ main { padding:20px; max-width:1500px; margin:0 auto }
   <div class="stat"><span class="stat-label">Avg saturation</span><span class="stat-value" id="s-sat">—</span></div>
   <div class="animals" id="s-animals"></div>
 </div>
+<section class="best-rail" id="best-rail" style="display:none">
+  <h2>Best of the night · most saturated 3</h2>
+  <div class="best-row" id="best-row"></div>
+</section>
 <main>
   <div class="grid" id="grid"></div>
   <div class="empty" id="empty">Loading the menagerie…</div>
@@ -2367,6 +2396,20 @@ function updateNext() {
   nextEl.textContent = 'next in ' + m + ':' + String(s).padStart(2,'0');
 }
 
+async function pollBest() {
+  try {
+    const r = await fetch('/api/drunk-animals/best?n=3');
+    const j = await r.json();
+    if (!j.best || !j.best.length) return;
+    const rail = document.getElementById('best-rail');
+    const row  = document.getElementById('best-row');
+    row.innerHTML = j.best.map(d => \`<a class="best-card" href="\${d.url}" target="_blank" rel="noopener" style="background-image:url('\${d.image_url}')">
+      <div class="info"><p class="t">\${d.title}</p><p class="id">#\${d.id} · sat \${(d.saturation||0).toFixed(2)}</p></div>
+    </a>\`).join('');
+    rail.style.display = 'block';
+  } catch (e) { console.warn('best poll failed', e); }
+}
+
 async function pollStats() {
   try {
     const r = await fetch('/api/drunk-animals/stats');
@@ -2383,8 +2426,10 @@ async function pollStats() {
 
 poll();
 pollStats();
+pollBest();
 setInterval(poll, 30_000);
 setInterval(pollStats, 60_000);
+setInterval(pollBest, 120_000);
 setInterval(updateNext, 1000);
 </script>
 </body></html>`);

← 4c0ff53 drunk-animals: /api/drunk-animals/stats + 'tonight in number  ·  back to Wallco Ai  ·  drunk-animals: generator status pill + auto-recap mode on /l 50ea14f →