From 37a2b97bfd61dfc6b5dc3cc03af768cd26092936 Mon Sep 17 00:00:00 2001 From: martbost Date: Sun, 6 Sep 2026 08:58:22 -0500 Subject: [PATCH] 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 --- ads.js | Bin 47850 -> 50301 bytes db.js | 1 + public/assets/my.js | 42 ++++++++++++++++++++++++++++++++++++----- public/assets/site.css | 6 ++++++ public/contract.html | 8 ++++---- public/index.html | 10 +++++----- public/ledger.html | 8 ++++---- public/my.html | 20 +++++++++++++++----- public/tx.html | 6 +++--- public/view.html | 4 ++-- public/wall.html | 6 +++--- server.js | 10 ++++++++++ 12 files changed, 90 insertions(+), 31 deletions(-) diff --git a/ads.js b/ads.js index 9827cdaf9fc0d1d28382fdee9555c25c605f0f87..99d511b8199763914e92d1b55b1c807ddf1a6371 100644 GIT binary patch delta 1988 zcmaJ?O>Epm6jlo*+g1^3AZ?Qt`Wi&m4$kfZA!#?=1e#4nBuG$-R6!Kci9MU0#yd8i zah6pY7I8p`QlV;kqeulLR8<^+y>sKrnF|u)zyXOPM-Xqu_Ih){Cwu&UzW2TFz4`O+ z!~cBz$al{UbsLn(IHDdzfh3Xzyb7Hlj=*Pp2cnn@U>szVLf=rxh=tGyB3K2Fbi};= zeGKp^m%(FxtfPR{4BF5lykjB>5KR(M6DUh$0~6qROt^j^5Wp72m{eznt+--|=^J9;$x zDyp9==hU_F*+X;cmodA0C8I=hAb?W@N1#cGhX=G&g#CGw(hazfh61R;YTVkQk;Qlz z%aW$WPK;Ostn*e>%98c*!Ofenv1ykWcm3F-!ZJ=aL`t1Lb=gbH0ILYk!TVwlu4WGnDG;0Au&;-;U%EW-aas1r#` zJZM`wzVV!b3$rs7{S5Np21rINvq%uzMp{YtbiFf`0amtRZ<|WEgsFv8zn&j6Xmt_O zm?qa7icl*>^I&r5DpLjIz0jD`fHh+_uZzw|*Zu?=K9O2l4)8!ii%P0>|N94b@lZn< zM)-}`_aTg!OMCA;y>?_I<)I30MoI6hXGWeVLH|dT{eZ67!YXG=ykh?fm+sRzz(6PR@gRMjca5OpW zP#OZ0KwQaoDOmVwCOhVm`EWgjb=~P2Vv^I8Oaw9^LdxZYjRCcoUD65(+vX+N2`SWS zwS25lf_p|mq)jkKf^8`o*4&SI4(yiPv|R&&@Kj-SSiSwtarNo%gM-(>!H+W4{ z7itS&?O{vxWNAf6CVi?u%!>nYmPn2DsxjSXE1B`i#>UF!K-POH2N6+Z( zf|o;oDswpd>haGN084{kgMvR#f>Qf_ka9>{Jg_2v7cy-U4^L)e7_Se(AJOa=N1`VR?3oOb{K delta 74 zcmV-Q0JZ=9hy&{N0 + '' + esc(i.title) + '' + + (i.by ? '' + esc(i.by) + '' : '') + '').join(''); + } catch (e) {} + } + // achievement badges: the milestone ladder as unlockable medals + share-to-image const BADGES = [ { key: 'payouts', label: 'Payouts On', sub: 'wallet linked', icon: '' }, @@ -212,6 +226,7 @@ setInboxBadge(d.inboxUnread || 0); if (d.sponsorMsg) showSponsorModal(d.sponsorMsg); renderBadges(d); + loadFeatured(); loadCharts(d); $('nextMove').textContent = nextMove(d); renderSteps(d); @@ -493,10 +508,25 @@ $('cSoloRow').hidden = t !== 'solo'; $('cSoloHint').hidden = t !== 'solo'; $('cVideoRow').hidden = t !== 'video'; + $('cFeaturedRow').hidden = t !== 'featured'; $('cTitle').placeholder = t === 'solo' ? 'Subject line (max 80)' : 'Headline (max 60)'; soloHint(); if (t === 'video') videoHint(); + if (t === 'featured') featHint(); }); + function featHint() { + if (!lastRates || !lastRates.featuredDurations) return; + if ($('cFeatDays') && !$('cFeatDays').options.length) + $('cFeatDays').innerHTML = lastRates.featuredDurations.map(dys => + '').join(''); + fetch('/api/featured/stats').then(r => r.json()).then(s => { + const dys = Number($('cFeatDays').value) || (lastRates.featuredDurations[0]); + $('cFeatHint').textContent = (s.activeCount || 0) + ' link' + (s.activeCount === 1 ? '' : 's') + + ' currently share the rotation — yours would make ' + ((s.activeCount || 0) + 1) + + '. Runs ' + dys + ' day' + (dys > 1 ? 's' : '') + ' for ' + (dys * lastRates.featuredPerDay) + ' credits.'; + }).catch(() => {}); + } + document.addEventListener('change', e => { if (e.target && e.target.id === 'cFeatDays') featHint(); }); // video composer: tier dropdown + upload + price hint function videoHint() { if (!lastRates || !lastRates.videoTiers) return; @@ -529,14 +559,16 @@ // in raw mode the source of truth is the textarea; sync it back first let soloBody = $('cSoloEd').innerHTML; if ($('cSoloRaw') && !$('cSoloRaw').hidden) soloBody = $('cSoloRaw').value; - const isVideo = $('cType').value === 'video'; - await api('/api/my/campaigns', { type: $('cType').value, name: $('cName').value, + const t = $('cType').value; + const isVideo = t === 'video', isFeat = t === 'featured'; + await api('/api/my/campaigns', { type: t, name: $('cName').value, targetUrl: $('cTarget').value, imageUrl: $('cImage').value, size: $('cSize').value, - title: isVideo ? $('cVideoTitle').value : $('cTitle').value, - body: $('cType').value === 'solo' ? soloBody : $('cBody').value, + title: isVideo ? $('cVideoTitle').value : isFeat ? $('cFeatTitle').value : $('cTitle').value, + body: t === 'solo' ? soloBody : $('cBody').value, videoUrl: $('cVideoUrl').value, watchSecs: Number($('cWatchSecs').value), + days: Number($('cFeatDays').value), ctaLabel: isVideo ? $('cVideoCta').value : $('cCtaLabel').value, - budget: Number($('cBudget').value) }); + budget: isFeat ? (Number($('cFeatDays').value) * (lastRates.featuredPerDay || 40)) : Number($('cBudget').value) }); IAP.status('Campaign is live. It starts serving right away.', 'ok'); $('cName').value = ''; $('cBudget').value = ''; $('cSoloEd').innerHTML = ''; $('cSoloRaw').value = ''; $('cCtaLabel').value = ''; diff --git a/public/assets/site.css b/public/assets/site.css index c0dd4d4..df82ebd 100644 --- a/public/assets/site.css +++ b/public/assets/site.css @@ -259,6 +259,12 @@ textarea{resize:vertical;font:inherit} #boBurger{display:block} .bo-content{padding:18px} } +/* ── featured rotation strip ── */ +.feat-strip{display:flex;flex-direction:column;gap:8px;margin-top:10px} +.feat-strip a{display:flex;justify-content:space-between;gap:10px;padding:11px 14px;border-radius:10px; + background:var(--panel);border:1px solid var(--line-strong);color:var(--ink);text-decoration:none;font-weight:600} +.feat-strip a:hover{border-color:var(--mint)} +.feat-strip .by{font-size:12px;color:var(--muted);font-weight:500;white-space:nowrap} /* ── achievement badges ── */ .badges{display:flex;gap:16px;flex-wrap:wrap;margin-top:12px} .badge-a{display:flex;flex-direction:column;align-items:center;gap:8px;width:120px;text-align:center} diff --git a/public/contract.html b/public/contract.html index d721155..d112fca 100644 --- a/public/contract.html +++ b/public/contract.html @@ -5,7 +5,7 @@ The contract | InstantAdPay - +
@@ -129,8 +129,8 @@
Advertising services with a performance referral program. Not an investment product; no income guarantees. Crypto transactions are irreversible. Never spend what you cannot afford.
- - - + + + diff --git a/public/index.html b/public/index.html index 99c1515..169340f 100644 --- a/public/index.html +++ b/public/index.html @@ -5,7 +5,7 @@ InstantAdPay: advertise and earn, locked in code - + @@ -410,9 +410,9 @@ - - - - + + + + diff --git a/public/ledger.html b/public/ledger.html index 74bd76e..1251ed4 100644 --- a/public/ledger.html +++ b/public/ledger.html @@ -5,7 +5,7 @@ Live ledger | InstantAdPay - +
@@ -25,8 +25,8 @@
- - - + + + diff --git a/public/my.html b/public/my.html index 2a2ce28..be34e90 100644 --- a/public/my.html +++ b/public/my.html @@ -4,7 +4,7 @@ Member area | InstantAdPay - + @@ -186,6 +186,10 @@
+ + - - - - + + + + diff --git a/public/tx.html b/public/tx.html index 4d0e1c5..751b335 100644 --- a/public/tx.html +++ b/public/tx.html @@ -4,7 +4,7 @@ Transaction | InstantAdPay - + @@ -33,7 +33,7 @@

← Back to the live ledger · Read the contract review

- - + + diff --git a/public/view.html b/public/view.html index a615915..1620966 100644 --- a/public/view.html +++ b/public/view.html @@ -4,7 +4,7 @@ Viewing ad — InstantAdPay - +