From 161adb250e4273d0bcaa160516bc950f5f46310f Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Mon, 3 Aug 2026 07:42:24 -0700 Subject: Self-host the punks; skipping avatar still publishes your punk MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit coinos.io serves 502 for a third of the punk set (both the numbered and hash endpoints), which is why a default avatar could come up blank. The 64 webps now ship with the app (53 salvaged, 11 gaps filled with donors) and every reference is same-origin. Skipping the avatar step publishes the deterministic punk as the kind-0 picture — your face is the same on every nostr client. Success screen: checkmark now sits below the title, bigger. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi --- build.js | 3 +++ src/app.js | 13 ++++++++----- src/recipient-search.js | 4 +++- src/style.css | 1 + static/punks/1.webp | Bin 0 -> 10266 bytes static/punks/10.webp | Bin 0 -> 4402 bytes static/punks/11.webp | Bin 0 -> 5176 bytes static/punks/12.webp | Bin 0 -> 4510 bytes static/punks/13.webp | Bin 0 -> 10516 bytes static/punks/14.webp | Bin 0 -> 4402 bytes static/punks/15.webp | Bin 0 -> 16518 bytes static/punks/16.webp | Bin 0 -> 4660 bytes static/punks/17.webp | Bin 0 -> 4146 bytes static/punks/18.webp | Bin 0 -> 14300 bytes static/punks/19.webp | Bin 0 -> 14734 bytes static/punks/2.webp | Bin 0 -> 2772 bytes static/punks/20.webp | Bin 0 -> 10502 bytes static/punks/21.webp | Bin 0 -> 41998 bytes static/punks/22.webp | Bin 0 -> 32682 bytes static/punks/23.webp | Bin 0 -> 41998 bytes static/punks/24.webp | Bin 0 -> 5026 bytes static/punks/25.webp | Bin 0 -> 22006 bytes static/punks/26.webp | Bin 0 -> 29244 bytes static/punks/27.webp | Bin 0 -> 23902 bytes static/punks/28.webp | Bin 0 -> 24820 bytes static/punks/29.webp | Bin 0 -> 8610 bytes static/punks/3.webp | Bin 0 -> 5026 bytes static/punks/30.webp | Bin 0 -> 36542 bytes static/punks/31.webp | Bin 0 -> 11690 bytes static/punks/32.webp | Bin 0 -> 41802 bytes static/punks/33.webp | Bin 0 -> 23902 bytes static/punks/34.webp | Bin 0 -> 7082 bytes static/punks/35.webp | Bin 0 -> 34532 bytes static/punks/36.webp | Bin 0 -> 25374 bytes static/punks/37.webp | Bin 0 -> 45616 bytes static/punks/38.webp | Bin 0 -> 6640 bytes static/punks/39.webp | Bin 0 -> 9580 bytes static/punks/4.webp | Bin 0 -> 4750 bytes static/punks/40.webp | Bin 0 -> 41802 bytes static/punks/41.webp | Bin 0 -> 32932 bytes static/punks/42.webp | Bin 0 -> 10818 bytes static/punks/43.webp | Bin 0 -> 9540 bytes static/punks/44.webp | Bin 0 -> 49350 bytes static/punks/45.webp | Bin 0 -> 25374 bytes static/punks/46.webp | Bin 0 -> 29892 bytes static/punks/47.webp | Bin 0 -> 49350 bytes static/punks/48.webp | Bin 0 -> 38754 bytes static/punks/49.webp | Bin 0 -> 28348 bytes static/punks/5.webp | Bin 0 -> 10790 bytes static/punks/50.webp | Bin 0 -> 23000 bytes static/punks/51.webp | Bin 0 -> 33426 bytes static/punks/52.webp | Bin 0 -> 29244 bytes static/punks/53.webp | Bin 0 -> 31586 bytes static/punks/54.webp | Bin 0 -> 4510 bytes static/punks/55.webp | Bin 0 -> 9324 bytes static/punks/56.webp | Bin 0 -> 28976 bytes static/punks/57.webp | Bin 0 -> 31206 bytes static/punks/58.webp | Bin 0 -> 33482 bytes static/punks/59.webp | Bin 0 -> 33412 bytes static/punks/6.webp | Bin 0 -> 4856 bytes static/punks/60.webp | Bin 0 -> 7268 bytes static/punks/61.webp | Bin 0 -> 28348 bytes static/punks/62.webp | Bin 0 -> 28012 bytes static/punks/63.webp | Bin 0 -> 26854 bytes static/punks/64.webp | Bin 0 -> 36532 bytes static/punks/7.webp | Bin 0 -> 4856 bytes static/punks/8.webp | Bin 0 -> 7484 bytes static/punks/9.webp | Bin 0 -> 7018 bytes 68 files changed, 15 insertions(+), 6 deletions(-) create mode 100644 static/punks/1.webp create mode 100644 static/punks/10.webp create mode 100644 static/punks/11.webp create mode 100644 static/punks/12.webp create mode 100644 static/punks/13.webp create mode 100644 static/punks/14.webp create mode 100644 static/punks/15.webp create mode 100644 static/punks/16.webp create mode 100644 static/punks/17.webp create mode 100644 static/punks/18.webp create mode 100644 static/punks/19.webp create mode 100644 static/punks/2.webp create mode 100644 static/punks/20.webp create mode 100644 static/punks/21.webp create mode 100644 static/punks/22.webp create mode 100644 static/punks/23.webp create mode 100644 static/punks/24.webp create mode 100644 static/punks/25.webp create mode 100644 static/punks/26.webp create mode 100644 static/punks/27.webp create mode 100644 static/punks/28.webp create mode 100644 static/punks/29.webp create mode 100644 static/punks/3.webp create mode 100644 static/punks/30.webp create mode 100644 static/punks/31.webp create mode 100644 static/punks/32.webp create mode 100644 static/punks/33.webp create mode 100644 static/punks/34.webp create mode 100644 static/punks/35.webp create mode 100644 static/punks/36.webp create mode 100644 static/punks/37.webp create mode 100644 static/punks/38.webp create mode 100644 static/punks/39.webp create mode 100644 static/punks/4.webp create mode 100644 static/punks/40.webp create mode 100644 static/punks/41.webp create mode 100644 static/punks/42.webp create mode 100644 static/punks/43.webp create mode 100644 static/punks/44.webp create mode 100644 static/punks/45.webp create mode 100644 static/punks/46.webp create mode 100644 static/punks/47.webp create mode 100644 static/punks/48.webp create mode 100644 static/punks/49.webp create mode 100644 static/punks/5.webp create mode 100644 static/punks/50.webp create mode 100644 static/punks/51.webp create mode 100644 static/punks/52.webp create mode 100644 static/punks/53.webp create mode 100644 static/punks/54.webp create mode 100644 static/punks/55.webp create mode 100644 static/punks/56.webp create mode 100644 static/punks/57.webp create mode 100644 static/punks/58.webp create mode 100644 static/punks/59.webp create mode 100644 static/punks/6.webp create mode 100644 static/punks/60.webp create mode 100644 static/punks/61.webp create mode 100644 static/punks/62.webp create mode 100644 static/punks/63.webp create mode 100644 static/punks/64.webp create mode 100644 static/punks/7.webp create mode 100644 static/punks/8.webp create mode 100644 static/punks/9.webp diff --git a/build.js b/build.js index 5efd3eb..3e42930 100644 --- a/build.js +++ b/build.js @@ -263,6 +263,9 @@ if (import.meta.main) { .replace('{{NWC_WAKE_FALLBACK}}', nwcSw ? '' : SW_WAKE_ONLY); await Bun.write('dist/sw.js', nwcSw ? swBody + '\n' + await buildSwNwc() : swBody); for (const f of STATIC) await Bun.write('dist/' + f, Bun.file('static/' + f)); + // default avatars, self-hosted since coinos.io's copies are half-broken + const { readdirSync } = await import('node:fs'); + for (const f of readdirSync('static/punks')) await Bun.write('dist/punks/' + f, Bun.file('static/punks/' + f)); const kb = (Buffer.byteLength(html) / 1024).toFixed(0); console.log(`✓ dist/index.html written (${kb} KB) — open it offline, no server needed`); diff --git a/src/app.js b/src/app.js index 562ca99..36fb0d2 100644 --- a/src/app.js +++ b/src/app.js @@ -6,7 +6,7 @@ import { Wallet, newMnemonic, isValidMnemonic, accountXpubFor, cacheKeyFor, utxoId, parseExtendedKey, xpubToZpub, encryptVault, decryptVault } from './wallet.js'; import { qrSvg } from './qr.js'; -import { makeSearcher, resultRows, searchable } from './recipient-search.js'; +import { makeSearcher, resultRows, searchable, punkUrl } from './recipient-search.js'; import { npubOf } from './nostr.js'; import { scanQr } from './scan.js'; import { dataSources, getSource, setSource, getNetwork, setNetwork, NETWORKS } from './api.js'; @@ -2007,7 +2007,7 @@ function shouldOnboard() { } const PUNK_PICKS = [7, 14, 21, 3, 33, 40, 47, 36, 61, 26, 12, 50]; -const punkImg = (n) => `https://coinos.io/api/public/punks/${n}.webp`; +const punkImg = (n) => `punks/${n}.webp`; async function onbUpload(file) { const fd = new FormData(); @@ -2110,7 +2110,10 @@ function onboardScreen() { ui.onbBusy = true; ui.onbError = ''; render(); try { const addr = featureHook('namesAddress'); - const fields = { name: addr ? addr.split('@')[0] : undefined, picture: o.avatar || undefined }; + // keeping the default still publishes it — their punk should be + // their face on every nostr client, not just here + const picture = o.avatar || (me ? 'https://v3.coinos.io/' + punkUrl(me) : undefined); + const fields = { name: addr ? addr.split('@')[0] : undefined, picture }; if (fields.name || fields.picture) await featureHook('publishProfile', fields); o.step = 'success'; } catch (e) { ui.onbError = e.message; } @@ -2121,8 +2124,8 @@ function onboardScreen() { // success return page([ h('div', { class: 'onb-confetti' }, ...Array.from({ length: 18 }, () => h('i'))), - h('div', { class: 'check-badge', style: 'align-self:center' }, '✓'), - title(t('onbDoneTitle')), + h('h2', { class: 'onb-title', style: 'text-align:center' }, t('onbDoneTitle')), + h('div', { class: 'check-badge onb-check' }, '✓'), h('p', { class: 'muted', style: 'margin:0;text-align:center' }, t('onbDoneBody')), h('button', { class: 'btn-primary btn-block', style: 'padding:14px', onClick: () => { try { localStorage.setItem(ONBOARDED_KEY, '1'); } catch {} diff --git a/src/recipient-search.js b/src/recipient-search.js index 2594488..553673e 100644 --- a/src/recipient-search.js +++ b/src/recipient-search.js @@ -13,8 +13,10 @@ import { queryOn, parseNostrPubkey, npubOf, PROFILE_RELAYS } from './nostr.js'; // coinos punks: the deterministic default avatar — same formula the coinos // app uses (last byte of the pubkey picks one of 64). Initials show through // if the image can't load (offline). +// Self-hosted (dist/punks) — coinos.io's own copies 502 for a third of the +// set. Same deterministic formula the coinos app uses. export const punkUrl = (pk) => - `https://coinos.io/api/public/punks/${Math.floor((parseInt(pk.slice(-2), 16) / 256) * 64) + 1}.webp`; + `punks/${Math.floor((parseInt(pk.slice(-2), 16) / 256) * 64) + 1}.webp`; export const fallbackAvatar = (h, pk, name, cls) => h('div', { class: cls + ' fallback' }, diff --git a/src/style.css b/src/style.css index 3dbeaaa..562db92 100644 --- a/src/style.css +++ b/src/style.css @@ -506,3 +506,4 @@ body::after { .tour-overlay { background: transparent; } .tour-card { position: fixed; left: 50%; transform: translateX(-50%); width: min(90vw, 360px); background: var(--paper); color: var(--ink); border: 1px solid var(--line-strong); border-radius: 14px; padding: 14px 16px; box-shadow: var(--shadow); z-index: 81; } @media (prefers-reduced-motion: reduce) { .onb-confetti i { animation: none; display: none; } } +.onb-check { width: 96px; height: 96px; font-size: 52px; align-self: center; margin: 6px 0; } diff --git a/static/punks/1.webp b/static/punks/1.webp new file mode 100644 index 0000000..b586aec Binary files /dev/null and b/static/punks/1.webp differ diff --git a/static/punks/10.webp b/static/punks/10.webp new file mode 100644 index 0000000..8b101f6 Binary files /dev/null and b/static/punks/10.webp differ diff --git a/static/punks/11.webp b/static/punks/11.webp new file mode 100644 index 0000000..7249ac5 Binary files /dev/null and b/static/punks/11.webp differ diff --git a/static/punks/12.webp b/static/punks/12.webp new file mode 100644 index 0000000..f8fb7b0 Binary files /dev/null and b/static/punks/12.webp differ diff --git a/static/punks/13.webp b/static/punks/13.webp new file mode 100644 index 0000000..b412231 Binary files /dev/null and b/static/punks/13.webp differ diff --git a/static/punks/14.webp b/static/punks/14.webp new file mode 100644 index 0000000..8b101f6 Binary files /dev/null and b/static/punks/14.webp differ diff --git a/static/punks/15.webp b/static/punks/15.webp new file mode 100644 index 0000000..3c119f8 Binary files /dev/null and b/static/punks/15.webp differ diff --git a/static/punks/16.webp b/static/punks/16.webp new file mode 100644 index 0000000..c72b298 Binary files /dev/null and b/static/punks/16.webp differ diff --git a/static/punks/17.webp b/static/punks/17.webp new file mode 100644 index 0000000..a32f6c5 Binary files /dev/null and b/static/punks/17.webp differ diff --git a/static/punks/18.webp b/static/punks/18.webp new file mode 100644 index 0000000..c70276d Binary files /dev/null and b/static/punks/18.webp differ diff --git a/static/punks/19.webp b/static/punks/19.webp new file mode 100644 index 0000000..50b7069 Binary files /dev/null and b/static/punks/19.webp differ diff --git a/static/punks/2.webp b/static/punks/2.webp new file mode 100644 index 0000000..a93e06a Binary files /dev/null and b/static/punks/2.webp differ diff --git a/static/punks/20.webp b/static/punks/20.webp new file mode 100644 index 0000000..f23875c Binary files /dev/null and b/static/punks/20.webp differ diff --git a/static/punks/21.webp b/static/punks/21.webp new file mode 100644 index 0000000..7b7fe31 Binary files /dev/null and b/static/punks/21.webp differ diff --git a/static/punks/22.webp b/static/punks/22.webp new file mode 100644 index 0000000..301e56b Binary files /dev/null and b/static/punks/22.webp differ diff --git a/static/punks/23.webp b/static/punks/23.webp new file mode 100644 index 0000000..7b7fe31 Binary files /dev/null and b/static/punks/23.webp differ diff --git a/static/punks/24.webp b/static/punks/24.webp new file mode 100644 index 0000000..f0e5676 Binary files /dev/null and b/static/punks/24.webp differ diff --git a/static/punks/25.webp b/static/punks/25.webp new file mode 100644 index 0000000..4d55807 Binary files /dev/null and b/static/punks/25.webp differ diff --git a/static/punks/26.webp b/static/punks/26.webp new file mode 100644 index 0000000..64cdb8e Binary files /dev/null and b/static/punks/26.webp differ diff --git a/static/punks/27.webp b/static/punks/27.webp new file mode 100644 index 0000000..0e220fc Binary files /dev/null and b/static/punks/27.webp differ diff --git a/static/punks/28.webp b/static/punks/28.webp new file mode 100644 index 0000000..b62214d Binary files /dev/null and b/static/punks/28.webp differ diff --git a/static/punks/29.webp b/static/punks/29.webp new file mode 100644 index 0000000..8ca659e Binary files /dev/null and b/static/punks/29.webp differ diff --git a/static/punks/3.webp b/static/punks/3.webp new file mode 100644 index 0000000..f0e5676 Binary files /dev/null and b/static/punks/3.webp differ diff --git a/static/punks/30.webp b/static/punks/30.webp new file mode 100644 index 0000000..eee45eb Binary files /dev/null and b/static/punks/30.webp differ diff --git a/static/punks/31.webp b/static/punks/31.webp new file mode 100644 index 0000000..85a6fb8 Binary files /dev/null and b/static/punks/31.webp differ diff --git a/static/punks/32.webp b/static/punks/32.webp new file mode 100644 index 0000000..c46a356 Binary files /dev/null and b/static/punks/32.webp differ diff --git a/static/punks/33.webp b/static/punks/33.webp new file mode 100644 index 0000000..0e220fc Binary files /dev/null and b/static/punks/33.webp differ diff --git a/static/punks/34.webp b/static/punks/34.webp new file mode 100644 index 0000000..7c2d01c Binary files /dev/null and b/static/punks/34.webp differ diff --git a/static/punks/35.webp b/static/punks/35.webp new file mode 100644 index 0000000..2a41a38 Binary files /dev/null and b/static/punks/35.webp differ diff --git a/static/punks/36.webp b/static/punks/36.webp new file mode 100644 index 0000000..07ad175 Binary files /dev/null and b/static/punks/36.webp differ diff --git a/static/punks/37.webp b/static/punks/37.webp new file mode 100644 index 0000000..1e46523 Binary files /dev/null and b/static/punks/37.webp differ diff --git a/static/punks/38.webp b/static/punks/38.webp new file mode 100644 index 0000000..bef34c5 Binary files /dev/null and b/static/punks/38.webp differ diff --git a/static/punks/39.webp b/static/punks/39.webp new file mode 100644 index 0000000..3df28f2 Binary files /dev/null and b/static/punks/39.webp differ diff --git a/static/punks/4.webp b/static/punks/4.webp new file mode 100644 index 0000000..f046e8a Binary files /dev/null and b/static/punks/4.webp differ diff --git a/static/punks/40.webp b/static/punks/40.webp new file mode 100644 index 0000000..c46a356 Binary files /dev/null and b/static/punks/40.webp differ diff --git a/static/punks/41.webp b/static/punks/41.webp new file mode 100644 index 0000000..7d74371 Binary files /dev/null and b/static/punks/41.webp differ diff --git a/static/punks/42.webp b/static/punks/42.webp new file mode 100644 index 0000000..1810d56 Binary files /dev/null and b/static/punks/42.webp differ diff --git a/static/punks/43.webp b/static/punks/43.webp new file mode 100644 index 0000000..cf4e8af Binary files /dev/null and b/static/punks/43.webp differ diff --git a/static/punks/44.webp b/static/punks/44.webp new file mode 100644 index 0000000..9639058 Binary files /dev/null and b/static/punks/44.webp differ diff --git a/static/punks/45.webp b/static/punks/45.webp new file mode 100644 index 0000000..07ad175 Binary files /dev/null and b/static/punks/45.webp differ diff --git a/static/punks/46.webp b/static/punks/46.webp new file mode 100644 index 0000000..6de78aa Binary files /dev/null and b/static/punks/46.webp differ diff --git a/static/punks/47.webp b/static/punks/47.webp new file mode 100644 index 0000000..9639058 Binary files /dev/null and b/static/punks/47.webp differ diff --git a/static/punks/48.webp b/static/punks/48.webp new file mode 100644 index 0000000..0736172 Binary files /dev/null and b/static/punks/48.webp differ diff --git a/static/punks/49.webp b/static/punks/49.webp new file mode 100644 index 0000000..3868f79 Binary files /dev/null and b/static/punks/49.webp differ diff --git a/static/punks/5.webp b/static/punks/5.webp new file mode 100644 index 0000000..4e2ebd4 Binary files /dev/null and b/static/punks/5.webp differ diff --git a/static/punks/50.webp b/static/punks/50.webp new file mode 100644 index 0000000..4569117 Binary files /dev/null and b/static/punks/50.webp differ diff --git a/static/punks/51.webp b/static/punks/51.webp new file mode 100644 index 0000000..343e4fa Binary files /dev/null and b/static/punks/51.webp differ diff --git a/static/punks/52.webp b/static/punks/52.webp new file mode 100644 index 0000000..64cdb8e Binary files /dev/null and b/static/punks/52.webp differ diff --git a/static/punks/53.webp b/static/punks/53.webp new file mode 100644 index 0000000..185e7ac Binary files /dev/null and b/static/punks/53.webp differ diff --git a/static/punks/54.webp b/static/punks/54.webp new file mode 100644 index 0000000..f8fb7b0 Binary files /dev/null and b/static/punks/54.webp differ diff --git a/static/punks/55.webp b/static/punks/55.webp new file mode 100644 index 0000000..18ae419 Binary files /dev/null and b/static/punks/55.webp differ diff --git a/static/punks/56.webp b/static/punks/56.webp new file mode 100644 index 0000000..e8a0123 Binary files /dev/null and b/static/punks/56.webp differ diff --git a/static/punks/57.webp b/static/punks/57.webp new file mode 100644 index 0000000..f1d0125 Binary files /dev/null and b/static/punks/57.webp differ diff --git a/static/punks/58.webp b/static/punks/58.webp new file mode 100644 index 0000000..06c8ac2 Binary files /dev/null and b/static/punks/58.webp differ diff --git a/static/punks/59.webp b/static/punks/59.webp new file mode 100644 index 0000000..740aafc Binary files /dev/null and b/static/punks/59.webp differ diff --git a/static/punks/6.webp b/static/punks/6.webp new file mode 100644 index 0000000..d04db94 Binary files /dev/null and b/static/punks/6.webp differ diff --git a/static/punks/60.webp b/static/punks/60.webp new file mode 100644 index 0000000..41491c6 Binary files /dev/null and b/static/punks/60.webp differ diff --git a/static/punks/61.webp b/static/punks/61.webp new file mode 100644 index 0000000..3868f79 Binary files /dev/null and b/static/punks/61.webp differ diff --git a/static/punks/62.webp b/static/punks/62.webp new file mode 100644 index 0000000..666eda2 Binary files /dev/null and b/static/punks/62.webp differ diff --git a/static/punks/63.webp b/static/punks/63.webp new file mode 100644 index 0000000..ca9c610 Binary files /dev/null and b/static/punks/63.webp differ diff --git a/static/punks/64.webp b/static/punks/64.webp new file mode 100644 index 0000000..394cf3f Binary files /dev/null and b/static/punks/64.webp differ diff --git a/static/punks/7.webp b/static/punks/7.webp new file mode 100644 index 0000000..d04db94 Binary files /dev/null and b/static/punks/7.webp differ diff --git a/static/punks/8.webp b/static/punks/8.webp new file mode 100644 index 0000000..060669f Binary files /dev/null and b/static/punks/8.webp differ diff --git a/static/punks/9.webp b/static/punks/9.webp new file mode 100644 index 0000000..7641699 Binary files /dev/null and b/static/punks/9.webp differ -- cgit v1.2.3