Badge cards: seven AI artworks for the hunting achievements, the hunter's name stamped on the ribbon server-side (ffmpeg), public share pages /b/<who>/<id> with OG cards, badge strip + share modal + unlock celebration on the board, Telegram photo post gated by OUTBOUND

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
martbost
2026-09-19 20:31:20 -05:00
parent 6338af9efe
commit 8eecc7c0cb
19 changed files with 156 additions and 14 deletions
+3 -3
View File
@@ -5,7 +5,7 @@
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Leaderboard · PolHunter</title>
<meta name="description" content="The hunters with the most finds this week, this month and all time. Every drip is on Polygon.">
<link rel="stylesheet" href="/style.css?v=9">
<link rel="stylesheet" href="/style.css?v=10">
</head>
<body>
<div class="wrap">
@@ -37,7 +37,7 @@
<section class="section">
<h2>Badges</h2>
<div class="sub">Earned automatically from your finds. They show next to your name up there and on your board.</div>
<div class="grid" id="badges"></div>
<div class="badge-strip" id="badges"></div>
</section>
<div class="adslot" data-ad="leaders"><!-- nas: 468x60 on phones, 728x90 on wider screens --><script>(function(){var m=window.innerWidth<600;document.write('<scr'+'ipt src="https://www.networkadspace.com/showadss.php?'+(m?'w=468&h=60&n=1&bw=468&bh=60':'w=728&h=90&n=1&bw=728&bh=90')+'&c=999"></scr'+'ipt>');})();</script></div>
@@ -63,7 +63,7 @@
if (pz.last && pz.last.winners.length) { document.getElementById('winners').style.display = 'block'; document.getElementById('winsub').textContent = 'Week of ' + pz.last.week + '.'; document.getElementById('winrows').innerHTML = pz.last.winners.map(w => '<div class="row lb"><span><b class="num">' + medal(w.rank) + '</b> ' + esc(w.who) + '</span><span class="site">' + w.finds + ' finds</span><span class="pol">+' + w.prizePol + ' POL prize</span></div>').join(''); }
} catch (e) {}
const b = await (await fetch('/api/badges')).json();
document.getElementById('badges').innerHTML = b.badges.map(x => '<div class="card"><div style="font-size:34px">' + x.icon + '</div><h3>' + esc(x.name) + '</h3><p>' + esc(x.why) + '</p>' + (me && me.badges && me.badges.some(y => y.id === x.id) ? '<p style="margin-top:8px"><span class="tag done">Earned</span></p>' : '') + '</div>').join('');
document.getElementById('badges').innerHTML = b.badges.map(x => { const got = me && me.badges && me.badges.some(y => y.id === x.id); return '<div class="badge-a' + (got ? '' : ' locked') + '"><img src="' + x.art + '" alt="' + esc(x.name) + '" loading="lazy"><div class="bl">' + x.icon + ' ' + esc(x.name) + '</div><div class="bs">' + esc(x.why) + '</div>' + (got ? '<p style="margin-top:8px"><span class="tag done">Earned</span></p>' : '') + '</div>'; }).join('');
show('week');
})();
</script>