hogwarts.dev pds dashboard
hogwarts.html edited
86 lines 2.5 kB view raw
1<!DOCTYPE html> 2<html lang="en"> 3<head> 4 <meta charset="UTF-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 <title>Hogwarts PDS</title> 7 <style> 8 body { 9 display: flex; 10 flex-direction: column; 11 align-items: center; 12 padding: 2rem; 13 } 14 ul { 15 list-style: none; 16 padding: 0; 17 } 18 li { 19 text-align: center; 20 margin: 0.5rem 0; 21 } 22 </style> 23</head> 24<body> 25 <h1>The Hogwarts PDS</h1> 26 <ul id="users"></ul> 27 28 <script> 29 const PDS_URL = "https://pds.hogwarts.dev"; 30 31 async function fetchAllRepos() { 32 const dids = []; 33 let cursor; 34 35 do { 36 const url = new URL(`${PDS_URL}/xrpc/com.atproto.sync.listRepos`); 37 if (cursor) url.searchParams.set("cursor", cursor); 38 39 const res = await fetch(url); 40 const data = await res.json(); 41 42 dids.push(...data.repos.map(r => r.did)); 43 cursor = data.cursor; 44 } while (cursor); 45 46 return dids; 47 } 48 49 async function fetchProfile(did) { 50 try { 51 const url = `${PDS_URL}/xrpc/com.atproto.repo.describeRepo?repo=${did}`; 52 const res = await fetch(url); 53 const data = await res.json(); 54 return { did, handle: data.handle || did }; 55 } catch { 56 return { did, handle: did }; 57 } 58 } 59 60 async function loadUsers() { 61 const usersEl = document.getElementById('users'); 62 63 try { 64 const dids = await fetchAllRepos(); 65 66 if (dids.length === 0) { 67 usersEl.innerHTML = '<li>No users found</li>'; 68 } else { 69 const profiles = await Promise.all(dids.map(fetchProfile)); 70 71 profiles.forEach(profile => { 72 const li = document.createElement('li'); 73 li.innerHTML = `<a href="https://bsky.app/profile/${profile.handle}" target="_blank">@${profile.handle}</a>`; 74 usersEl.appendChild(li); 75 }); 76 } 77 } catch (error) { 78 usersEl.innerHTML = '<li>Error loading users</li>'; 79 console.error(error); 80 } 81 } 82 83 loadUsers(); 84 </script> 85</body> 86</html>