The only PDS hosted on a jailbroken chromebook
at main 9.1 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>Create Account - pds.madebydanny.uk</title> 7 <style> 8 * { 9 box-sizing: border-box; 10 margin: 0; 11 padding: 0; 12 } 13 14 body { 15 background-color: #0d0d0d; 16 color: #f0f0f0; 17 font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif; 18 padding: 2rem; 19 min-height: 100vh; 20 display: flex; 21 align-items: center; 22 justify-content: center; 23 } 24 25 .container { 26 max-width: 500px; 27 width: 100%; 28 background: #1a1a1a; 29 border-radius: 12px; 30 padding: 2rem; 31 box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3); 32 } 33 34 h1 { 35 color: #4eaaff; 36 margin-bottom: 0.5rem; 37 font-size: 1.75rem; 38 } 39 40 .subtitle { 41 color: #999; 42 margin-bottom: 2rem; 43 font-size: 0.9rem; 44 } 45 46 .form-group { 47 margin-bottom: 1.5rem; 48 } 49 50 label { 51 display: block; 52 margin-bottom: 0.5rem; 53 color: #ccc; 54 font-size: 0.9rem; 55 font-weight: 500; 56 } 57 58 input[type="text"], 59 input[type="email"], 60 input[type="password"], 61 select { 62 width: 100%; 63 padding: 0.75rem; 64 background: #0d0d0d; 65 border: 1px solid #333; 66 border-radius: 6px; 67 color: #f0f0f0; 68 font-size: 1rem; 69 transition: border-color 0.2s; 70 } 71 72 input[type="text"]:focus, 73 input[type="email"]:focus, 74 input[type="password"]:focus, 75 select:focus { 76 outline: none; 77 border-color: #4eaaff; 78 } 79 80 .handle-input-wrapper { 81 display: flex; 82 flex-direction: column; 83 gap: 0.5rem; 84 } 85 86 .helper-text { 87 font-size: 0.8rem; 88 color: #666; 89 margin-top: 0.25rem; 90 } 91 92 button { 93 width: 100%; 94 padding: 0.875rem; 95 background: #4eaaff; 96 color: #fff; 97 border: none; 98 border-radius: 6px; 99 font-size: 1rem; 100 font-weight: 600; 101 cursor: pointer; 102 transition: background 0.2s; 103 } 104 105 button:hover { 106 background: #3d99ee; 107 } 108 109 button:disabled { 110 background: #333; 111 cursor: not-allowed; 112 } 113 114 .error { 115 background: #ff4444; 116 color: white; 117 padding: 0.75rem; 118 border-radius: 6px; 119 margin-bottom: 1rem; 120 display: none; 121 } 122 123 .success { 124 background: #44ff44; 125 color: #000; 126 padding: 0.75rem; 127 border-radius: 6px; 128 margin-bottom: 1rem; 129 display: none; 130 } 131 132 .back-link { 133 text-align: center; 134 margin-top: 1.5rem; 135 } 136 137 .back-link a { 138 color: #4eaaff; 139 text-decoration: none; 140 font-size: 0.9rem; 141 } 142 143 .back-link a:hover { 144 text-decoration: underline; 145 } 146 147 .loading { 148 display: none; 149 text-align: center; 150 color: #4eaaff; 151 margin-top: 1rem; 152 } 153 </style> 154</head> 155<body> 156 <div class="container"> 157 <h1>Create Account</h1> 158 <p class="subtitle">Join pds.madebydanny.uk on the AT Protocol network</p> 159 160 <div class="error" id="error"></div> 161 <div class="success" id="success"></div> 162 163 <form id="createAccountForm"> 164 <div class="form-group"> 165 <label for="handle">Handle *</label> 166 <div class="handle-input-wrapper"> 167 <input 168 type="text" 169 id="handle" 170 name="handle" 171 required 172 placeholder="yourname" 173 pattern="[a-zA-Z0-9-]+" 174 autocomplete="off" 175 > 176 <select id="domain" name="domain" required> 177 <option value=".pds.madebydanny.uk">.pds.madebydanny.uk</option> 178 <option value=".pds.danielmorrisey.com">.pds.danielmorrisey.com</option> 179 <option value=".good-example.com">.good-example.com</option> 180 <option value=".mbdio.uk">.mbdio.uk</option> 181 <option value=".certifiedshitposter.com">.certifiedshitposter.com</option> 182 </select> 183 </div> 184 <div class="helper-text">Letters, numbers, and hyphens only</div> 185 </div> 186 187 <div class="form-group"> 188 <label for="email">Email *</label> 189 <input 190 type="email" 191 id="email" 192 name="email" 193 required 194 placeholder="you@example.com" 195 autocomplete="email" 196 > 197 </div> 198 199 <div class="form-group"> 200 <label for="password">Password *</label> 201 <input 202 type="password" 203 id="password" 204 name="password" 205 required 206 minlength="8" 207 placeholder="At least 8 characters" 208 autocomplete="new-password" 209 > 210 </div> 211 212 <button type="submit" id="submitBtn">Create Account</button> 213 <div class="loading" id="loading">Creating your account...</div> 214 </form> 215 216 <div class="back-link"> 217 <a href="/">← Back to home</a> 218 </div> 219 </div> 220 221 <script> 222 const form = document.getElementById('createAccountForm'); 223 const errorDiv = document.getElementById('error'); 224 const successDiv = document.getElementById('success'); 225 const submitBtn = document.getElementById('submitBtn'); 226 const loadingDiv = document.getElementById('loading'); 227 228 function showError(message) { 229 errorDiv.textContent = message; 230 errorDiv.style.display = 'block'; 231 successDiv.style.display = 'none'; 232 } 233 234 function showSuccess(message) { 235 successDiv.textContent = message; 236 successDiv.style.display = 'block'; 237 errorDiv.style.display = 'none'; 238 } 239 240 function hideMessages() { 241 errorDiv.style.display = 'none'; 242 successDiv.style.display = 'none'; 243 } 244 245 form.addEventListener('submit', async (e) => { 246 e.preventDefault(); 247 hideMessages(); 248 249 const handle = document.getElementById('handle').value.trim(); 250 const domain = document.getElementById('domain').value; 251 const email = document.getElementById('email').value.trim(); 252 const password = document.getElementById('password').value; 253 254 // Validate handle 255 if (!/^[a-zA-Z0-9-]+$/.test(handle)) { 256 showError('Handle can only contain letters, numbers, and hyphens'); 257 return; 258 } 259 260 // Build full handle 261 const fullHandle = `${handle}${domain}`; 262 263 // Disable form 264 submitBtn.disabled = true; 265 loadingDiv.style.display = 'block'; 266 267 try { 268 // Create account via AT Protocol API 269 const response = await fetch('/xrpc/com.atproto.server.createAccount', { 270 method: 'POST', 271 headers: { 272 'Content-Type': 'application/json', 273 }, 274 body: JSON.stringify({ 275 email: email, 276 handle: fullHandle, 277 password: password, 278 }) 279 }); 280 281 const data = await response.json(); 282 283 if (!response.ok) { 284 throw new Error(data.message || 'Failed to create account'); 285 } 286 287 // Account created successfully 288 showSuccess('Account created successfully! You can now log in to Bluesky with your credentials.'); 289 290 // Clear form 291 form.reset(); 292 293 } catch (error) { 294 console.error('Error:', error); 295 showError(error.message || 'An error occurred. Please try again.'); 296 } finally { 297 submitBtn.disabled = false; 298 loadingDiv.style.display = 'none'; 299 } 300 }); 301 </script> 302</body> 303</html>