forked from
danielmorrisey.com/pdslist
A community-maintained directory of Bluesky Personal Data Servers (PDS).
1// Load PDS data and populate table
2document.addEventListener('DOMContentLoaded', function() {
3 loadPDSData();
4});
5
6async function loadPDSData() {
7 const loading = document.getElementById('loading');
8 const content = document.getElementById('content');
9 const tableBody = document.getElementById('table-body');
10 const noData = document.getElementById('no-data');
11 const serverCount = document.getElementById('server-count');
12
13 try {
14 const response = await fetch('./pdslist.json');
15 const pdsData = await response.json();
16
17 // Hide loading
18 loading.style.display = 'none';
19 content.style.display = 'block';
20
21 if (pdsData.length === 0) {
22 noData.style.display = 'block';
23 return;
24 }
25
26 // Update server count
27 serverCount.textContent = pdsData.length;
28
29 // Populate table
30 pdsData.forEach(pds => {
31 const row = createTableRow(pds);
32 tableBody.appendChild(row);
33 });
34
35 } catch (error) {
36 console.error('Error loading PDS data:', error);
37 loading.innerHTML = '<p style="color: red;">Error loading database. Please check console.</p>';
38 }
39}
40
41function createTableRow(pds) {
42 const row = document.createElement('tr');
43
44 // URL
45 const urlCell = document.createElement('td');
46 const urlLink = document.createElement('a');
47 urlLink.href = pds.url;
48 urlLink.target = '_blank';
49 urlLink.textContent = pds.url;
50 urlCell.appendChild(urlLink);
51 row.appendChild(urlCell);
52
53 // Handles
54 const handlesCell = document.createElement('td');
55 if (pds.supportedHandles && pds.supportedHandles.length > 0) {
56 handlesCell.textContent = pds.supportedHandles.join(', ');
57 } else {
58 handlesCell.textContent = 'N/A';
59 }
60 row.appendChild(handlesCell);
61
62 // Maintainer
63 const maintainerCell = document.createElement('td');
64 if (pds.maintainer) {
65 const link = document.createElement('a');
66 link.href = `https://madebydanny.uk/followonbsky?did=${pds.maintainer}`;
67 link.target = '_blank';
68 link.textContent = pds.maintainer;
69 maintainerCell.appendChild(link);
70 } else {
71 maintainerCell.textContent = '—';
72 }
73 row.appendChild(maintainerCell);
74
75 // Contact Email
76 const emailCell = document.createElement('td');
77 if (pds.contactEmail) {
78 const link = document.createElement('a');
79 link.href = `mailto:${pds.contactEmail}`;
80 link.textContent = pds.contactEmail;
81 emailCell.appendChild(link);
82 } else {
83 emailCell.textContent = '—';
84 }
85 row.appendChild(emailCell);
86
87 // Invite Code Required
88 const inviteCell = document.createElement('td');
89 inviteCell.textContent = pds.inviteCodeRequired ? 'Yes' : 'No';
90 row.appendChild(inviteCell);
91
92 // Terms of Service
93 const tosCell = document.createElement('td');
94 if (pds.tosUrl) {
95 const link = document.createElement('a');
96 link.href = pds.tosUrl;
97 link.target = '_blank';
98 link.rel = 'noopener noreferrer';
99 link.textContent = 'Link';
100 tosCell.appendChild(link);
101 } else {
102 tosCell.textContent = '—';
103 }
104 row.appendChild(tosCell);
105
106 // Privacy Policy
107 const privacyCell = document.createElement('td');
108 if (pds.privacyUrl) {
109 const link = document.createElement('a');
110 link.href = pds.privacyUrl;
111 link.target = '_blank';
112 link.rel = 'noopener noreferrer';
113 link.textContent = 'Link';
114 privacyCell.appendChild(link);
115 } else {
116 privacyCell.textContent = '—';
117 }
118 row.appendChild(privacyCell);
119
120 return row;
121}