decentralized crowd-sourced service status tracker on ATProto
1 <h1>Known Services</h1>
2 <p>Real-time crowd-sourced status from the AT Protocol network.</p>
3
4 <div id="services-grid" class="grid">
5 <% services.forEach(s => { %>
6 <div class="service-card" data-domain="<%= s.domain %>">
7 <div class="service-name"><%= s.name %></div>
8 <div class="service-domain">@<%= s.domain %></div>
9 <div class="service-status" id="status-<%= s.domain.replace(/\./g,'-') %>">
10 <span class="status-text">Checking…</span>
11 <span class="status-count"></span>
12 </div>
13 <button class="issue-btn" onclick="reportIssue('<%= s.domain %>')">
14 Having issues
15 </button>
16 </div>
17 <% }) %>
18 </div>
19
20 <p style="margin-top: 3rem; opacity: 0.6; font-size: 0.9rem;">
21 Reports are pulled live from the decentralized network • no central database
22 </p>
23
24<script>
25// Auto-refresh every 15 seconds + on load
26async function updateStatuses() {
27 const res = await fetch('/api/status');
28 const data = await res.json();
29 for (const [domain, info] of Object.entries(data)) {
30 const el = document.getElementById('status-' + domain.replace(/\./g,'-'));
31 if (!el) continue;
32 el.innerHTML = `
33 <span class="status-${info.current}">● ${info.current.toUpperCase()}</span>
34 ${info.reports > 0 ? `<span class="status-count">(${info.reports} reports)</span>` : ''}
35 `;
36 }
37}
38updateStatuses();
39setInterval(updateStatuses, 15000);
40
41// Fake report button (we’ll make real later)
42function reportIssue(domain) {
43 if (confirm(`Report issue with ${domain}? (Login coming soon)`)) {
44 alert(`Reported issue with ${domain} — thanks!`);
45 }
46}
47</script>