← back to Purelymail Fleet Viewer
viewer: add fleet-cover hero with 1-up/4-up rotate toggle
2aafd6e119a9541f4e789ce9428a1dec5fd1b22f · 2026-05-18 17:28:30 -0700 · SteveStudio2
Files touched
Diff
commit 2aafd6e119a9541f4e789ce9428a1dec5fd1b22f
Author: SteveStudio2 <steve@designerwallcoverings.com>
Date: Mon May 18 17:28:30 2026 -0700
viewer: add fleet-cover hero with 1-up/4-up rotate toggle
---
public/index.html | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 59 insertions(+)
diff --git a/public/index.html b/public/index.html
index 0c66567..7acdb01 100644
--- a/public/index.html
+++ b/public/index.html
@@ -61,6 +61,22 @@
.shot{width:100%;height:230px;object-fit:cover;object-position:top;
background:#fff;display:block}
.shot.tall{height:540px}
+ /* cover hero — 1 hi-res vs 4-square */
+ .hero-bar{display:flex;align-items:center;justify-content:space-between;
+ gap:12px;margin:18px 0 6px}
+ .hero-bar h2{margin:0}
+ #heroToggle{background:var(--gold);color:#1a1710;border:0;border-radius:6px;
+ padding:7px 14px;font-size:12px;font-weight:600;cursor:pointer}
+ #heroToggle:hover{filter:brightness(1.08)}
+ .hero{border:1px solid var(--line);border-radius:10px;overflow:hidden;margin-bottom:8px}
+ .hero.one img{width:100%;height:460px;object-fit:cover;object-position:top;
+ background:#fff;display:block}
+ .hero.quad{display:grid;grid-template-columns:1fr 1fr;gap:2px;background:var(--line)}
+ .hero.quad img{width:100%;height:225px;object-fit:cover;object-position:top;
+ background:#fff;display:block}
+ .hero a{position:relative;display:block;text-decoration:none}
+ .hero-cap{position:absolute;left:9px;bottom:9px;background:rgba(13,12,10,.8);
+ color:var(--gold);font-size:11px;padding:3px 9px;border-radius:4px}
.dcard .meta{padding:8px 10px}
.dcard .meta .dn{font-size:12px;font-weight:600}
.dcard .meta .dn a{color:var(--gold);text-decoration:none}
@@ -83,6 +99,12 @@
<div class="wrap">
<div id="err"></div>
+ <div class="hero-bar">
+ <h2>Fleet Cover</h2>
+ <button id="heroToggle">◱ Show 4-up</button>
+ </div>
+ <div id="hero" class="hero quad"></div>
+
<h2>Fleet Health — 211 domains</h2>
<div class="cards" id="cards"></div>
<div class="sub" id="healthnote"></div>
@@ -187,6 +209,7 @@ function render(d){
// avoids reloading every iframe on the 15s auto-refresh
const sig = JSON.stringify(d.health.domains || []);
if (sig !== lastSig){ lastSig = sig; draw(); }
+ if (!heroDrawn){ heroDrawn = true; drawHero(); }
$('#foot').textContent = 'purelymail-fleet-viewer · 127.0.0.1:9779 · health source: email-deliverability-agent/output/domain-health.json';
}
@@ -324,6 +347,41 @@ function setDensity(){
localStorage.setItem('pmfv.density', n);
}
+// --- fleet cover hero ------------------------------------------------------
+// One big hi-res screenshot, or a 2x2 of four lower-res ones. The toggle
+// re-picks four random fleet domains so each press rotates through the fleet.
+let heroMode = localStorage.getItem('pmfv.heroMode') || '4up';
+let heroPick = [];
+let heroDrawn = false;
+
+function pickHeroDomains(n){
+ const pool = (DATA && DATA.health.domains || []).map(d=>d.domain);
+ const out = [];
+ while (out.length < n && pool.length)
+ out.push(pool.splice(Math.floor(Math.random()*pool.length),1)[0]);
+ return out;
+}
+function heroCard(domain){
+ return '<a href="https://'+domain+'" target="_blank" rel="noopener">'
+ + '<img src="/api/shot?domain='+encodeURIComponent(domain)
+ + '" loading="lazy" onerror="shotFail(this,\''+domain+'\','+(heroMode==='1up'?460:225)+')">'
+ + '<span class="hero-cap">'+domain+'</span></a>';
+}
+function drawHero(){
+ if (!DATA) return;
+ if (heroPick.length < 4) heroPick = pickHeroDomains(4);
+ const h = $('#hero');
+ if (heroMode==='1up'){ h.className='hero one'; h.innerHTML = heroCard(heroPick[0]); }
+ else { h.className='hero quad'; h.innerHTML = heroPick.slice(0,4).map(heroCard).join(''); }
+ $('#heroToggle').textContent = heroMode==='1up' ? '◱ Show 4-up' : '▢ Show 1 hi-res';
+}
+function toggleHero(){
+ heroMode = heroMode==='1up' ? '4up' : '1up';
+ localStorage.setItem('pmfv.heroMode', heroMode);
+ heroPick = pickHeroDomains(4); // re-pick so each toggle rotates the fleet
+ drawHero();
+}
+
async function load(){
try{
const r = await fetch('/api/status');
@@ -343,6 +401,7 @@ async function load(){
draw();
}));
$('#density').addEventListener('input', setDensity);
+$('#heroToggle').addEventListener('click', toggleHero);
setDensity();
load();
← d0d1ab6 viewer: server-rendered screenshots for every domain + Site
·
back to Purelymail Fleet Viewer
·
gitignore: broaden patterns to cover bak/pre/swp/orig/rej de e42a811 →