declarative relay deployment on hetzner relay-eval.waow.tech
atproto relay
14
fork

Configure Feed

Select the types of activity you want to include in your feed.

relay-eval dashboard: vertical legend with profile links, run-by column

- operator legend uses 3-column grid (no more horizontal overflow)
- all operator names link to bsky.app profiles
- added "run by" column to coverage table with linked names
- follows Pulsar's pattern: @handle → bsky.app/profile/handle

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

zzstoatzz b9a47de9 4ccc24fc

+31 -18
+31 -18
relay-eval/src/static/index.html
··· 32 32 33 33 /* operator legend */ 34 34 .op-legend { 35 - display: flex; flex-wrap: wrap; gap: 0.5rem 1.1rem; 35 + display: grid; grid-template-columns: repeat(3, auto); gap: 0.25rem 1.5rem; 36 36 margin-top: 1.1rem; font-size: 0.8rem; color: var(--muted); 37 + width: fit-content; 37 38 } 38 - .op-legend span { white-space: nowrap; } 39 + .op-legend a { color: var(--muted); text-decoration: none; } 40 + .op-legend a:hover { color: var(--fg); text-decoration: underline; } 39 41 .sym { font-size: 0.85em; margin-right: 0.3rem; } 42 + .run-by { font-size: 0.75rem; color: var(--muted); } 43 + .run-by a { color: var(--muted); text-decoration: none; } 44 + .run-by a:hover { color: var(--fg); text-decoration: underline; } 40 45 41 46 /* sections */ 42 47 .sec { font-size: 0.9rem; font-weight: 600; margin-top: 2rem; margin-bottom: 0.2rem; } ··· 115 120 116 121 <script> 117 122 const ops = { 118 - 'bsky.network': { name: 'bluesky', sym: '◆', color: '#58a6ff' }, 119 - 'relay1.us-east.bsky.network': { name: 'bluesky', sym: '◆', color: '#58a6ff' }, 120 - 'relay1.us-west.bsky.network': { name: 'bluesky', sym: '◆', color: '#58a6ff' }, 121 - 'zlay.waow.tech': { name: '@zzstoatzz.io', sym: '▲', color: '#3fb950' }, 122 - 'relay.waow.tech': { name: '@zzstoatzz.io', sym: '▲', color: '#3fb950' }, 123 - 'relay.bas.sh': { name: '@bas.sh', sym: '■', color: '#f0883e' }, 124 - 'northamerica.firehose.network': { name: '@sri.xyz', sym: '●', color: '#bc8cff' }, 125 - 'asia.firehose.network': { name: '@sri.xyz', sym: '●', color: '#bc8cff' }, 126 - 'europe.firehose.network': { name: '@sri.xyz', sym: '●', color: '#bc8cff' }, 127 - 'relay.fire.hose.cam': { name: '@bad-example.com', sym: '◇', color: '#f85149' }, 128 - 'relay3.fr.hose.cam': { name: '@bad-example.com', sym: '◇', color: '#f85149' }, 129 - 'relay.xero.systems': { name: '@besaid.zone', sym: '★', color: '#d29922' }, 130 - 'atproto.africa': { name: 'blacksky', sym: '◎', color: '#da7dae' }, 123 + 'bsky.network': { name: 'bluesky', sym: '◆', color: '#58a6ff', url: 'https://bsky.app' }, 124 + 'relay1.us-east.bsky.network': { name: 'bluesky', sym: '◆', color: '#58a6ff', url: 'https://bsky.app' }, 125 + 'relay1.us-west.bsky.network': { name: 'bluesky', sym: '◆', color: '#58a6ff', url: 'https://bsky.app' }, 126 + 'zlay.waow.tech': { name: '@zzstoatzz.io', sym: '▲', color: '#3fb950', url: 'https://bsky.app/profile/zzstoatzz.io' }, 127 + 'relay.waow.tech': { name: '@zzstoatzz.io', sym: '▲', color: '#3fb950', url: 'https://bsky.app/profile/zzstoatzz.io' }, 128 + 'relay.bas.sh': { name: '@bas.sh', sym: '■', color: '#f0883e', url: 'https://bsky.app/profile/bas.sh' }, 129 + 'northamerica.firehose.network': { name: '@sri.xyz', sym: '●', color: '#bc8cff', url: 'https://bsky.app/profile/sri.xyz' }, 130 + 'asia.firehose.network': { name: '@sri.xyz', sym: '●', color: '#bc8cff', url: 'https://bsky.app/profile/sri.xyz' }, 131 + 'europe.firehose.network': { name: '@sri.xyz', sym: '●', color: '#bc8cff', url: 'https://bsky.app/profile/sri.xyz' }, 132 + 'relay.fire.hose.cam': { name: '@bad-example.com', sym: '◇', color: '#f85149', url: 'https://bsky.app/profile/bad-example.com' }, 133 + 'relay3.fr.hose.cam': { name: '@bad-example.com', sym: '◇', color: '#f85149', url: 'https://bsky.app/profile/bad-example.com' }, 134 + 'relay.xero.systems': { name: '@besaid.zone', sym: '★', color: '#d29922', url: 'https://bsky.app/profile/besaid.zone' }, 135 + 'atproto.africa': { name: 'blacksky', sym: '◎', color: '#da7dae', url: 'https://bsky.app/profile/blacksky.dev' }, 131 136 'relay.upcloud.world': { name: 'upcloud', sym: '▽', color: '#39d2c0' }, 132 - 'relay.feeds.blue': { name: '@mackuba.eu', sym: '⬡', color: '#d2a8ff' }, 137 + 'relay.feeds.blue': { name: '@mackuba.eu', sym: '⬡', color: '#d2a8ff', url: 'https://bsky.app/profile/mackuba.eu' }, 133 138 }; 134 139 135 140 function op(h) { return ops[h] || { name: h.split('.').slice(-2).join('.'), sym: '·', color: '#8b949e' }; } ··· 206 211 for (const s of data.stats) { const o = op(s.host); seen[o.name] = o; } 207 212 h += `<div class="op-legend">`; 208 213 for (const [name, o] of Object.entries(seen)) { 209 - h += `<span><span class="sym" style="color:${o.color}">${o.sym}</span> ${name}</span>`; 214 + const label = o.url 215 + ? `<a href="${o.url}" target="_blank"><span class="sym" style="color:${o.color}">${o.sym}</span> ${name}</a>` 216 + : `<span><span class="sym" style="color:${o.color}">${o.sym}</span> ${name}</span>`; 217 + h += label; 210 218 } 211 219 h += `</div>`; 212 220 ··· 223 231 h += `<p class="sec-desc">each relay independently discovers PDS hosts. coverage = accounts this relay saw / accounts any relay saw.</p>`; 224 232 225 233 h += `<table><thead><tr>`; 226 - h += `<th>relay</th><th class="num">events</th><th class="num">accounts</th>`; 234 + h += `<th>relay</th><th>run by</th><th class="num">events</th><th class="num">accounts</th>`; 227 235 h += `<th class="num">coverage</th><th class="num">missed</th><th></th>`; 228 236 h += `</tr></thead><tbody>`; 229 237 ··· 231 239 for (const s of g.relays) { 232 240 const d = rd[s.host] || { coverage_gap: 0, unresolvable: 0, deactivated: 0 }; 233 241 const missed = d.coverage_gap + d.unresolvable + d.deactivated; 242 + const o = op(s.host); 243 + const byLink = o.url 244 + ? `<a href="${o.url}" target="_blank">${o.name}</a>` 245 + : o.name; 234 246 h += `<tr${s.events === 0 ? ' class="dimmed"' : ''}>`; 235 247 h += `<td>${rn(s.host)}</td>`; 248 + h += `<td class="run-by">${byLink}</td>`; 236 249 h += `<td class="num">${s.events.toLocaleString()}</td>`; 237 250 h += `<td class="num">${s.unique_dids.toLocaleString()}</td>`; 238 251 h += `<td class="num">${pct(s.unique_dids, union)}</td>`;