Featured rotation format: duration-priced link rotation with disclosed dilution

- New 'featured' type: headline + link + 1/2/7 day run, flat up-front price (40cr/day)
- Composer discloses dilution (N links share the rotation, yours makes N+1) before buying
- Overview featured strip shows the live rotation; expires automatically

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
martbost
2026-09-06 08:58:22 -05:00
parent b25b4c67fe
commit 37a2b97bfd
12 changed files with 90 additions and 31 deletions
+10
View File
@@ -652,6 +652,16 @@ const server = http.createServer(async (req, res) => {
if (!s || !s.email) return json(res, 401, { error: 'Sign in first.' });
return json(res, 200, await messages.markRead(s.email, m[1]));
}
// -- featured rotation: the live featured links + dilution stats
if (p === '/api/featured' && req.method === 'GET') {
const items = await ads.serveFeatured();
const names = await accounts.namesForMembers([...new Set(items.map(i => i.memberId).filter(Boolean))]);
for (const i of items) i.by = (i.memberId && names[i.memberId]) ? '@' + names[i.memberId] : (i.memberId ? 'member #' + i.memberId : null);
return json(res, 200, { items });
}
if (p === '/api/featured/stats' && req.method === 'GET') {
return json(res, 200, await ads.featuredStats());
}
// -- QR code (SVG) for any InstantAdPay URL — used on bio/wall pages
if (p === '/api/qr' && req.method === 'GET') {
const data = String(u.searchParams.get('d') || '').slice(0, 300);