madebydanny.uk written in html, css, and a lot of JavaScript I don't understand madebydanny.uk
html css javascript
1
fork

Configure Feed

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

I did a thing

+374 -67
+374 -67
cdn.html
··· 5 5 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 6 6 <title>MBD CDN - madebydanny.uk</title> 7 7 <script src="https://kit.fontawesome.com/0ca27f8db1.js" crossorigin="anonymous"></script> 8 - <link rel="icon" href="https://imrs.madebydanny.uk/?url=https://cloudflareisawesome.madebydanny.uk/madebydanny.uk/seo/favicon.webp"> 9 - <meta name="description" content="Private Cloudflare R2 Storage for madebydanny.uk"> 8 + <link rel="icon" href="https://public-cdn.madebydanny.uk/user-content/2026-01-30/33913bec-bc2f-4e6c-a474-2ef8f8c00197"> 9 + <meta name="description" content="The MBD CDN is a network of servers located around the world powered by the Cloudflare global network."> 10 10 <meta property="og:title" content="MBD CDN - madebydanny.uk"> 11 - <meta property="og:description" content="Private Cloudflare R2 Storage"> 11 + <meta property="og:description" content="The MBD CDN is a network of servers located around the world powered by the Cloudflare global network."> 12 + <meta property="og:image" content="https://imrs.madebydanny.uk?url=https://public-cdn.madebydanny.uk/user-content/2026-01-30/090c515c-827b-4b24-89a5-83ac8db7c4f1.png"> 12 13 <meta property="og:type" content="website"> 13 14 14 15 <style> 15 - /* --- THEME VARIABLES (Matching your site) --- */ 16 + /* --- THEME VARIABLES --- */ 16 17 :root { 17 18 --card-bg: #4a2b32; 18 19 --post-bg: #1e1e1e; ··· 22 23 --border: rgba(255,255,255,0.1); 23 24 --success-green: #34c759; 24 25 --error-red: #ff6b6b; 26 + --stat-card-bg: #2a1a21; 27 + } 28 + 29 + * { 30 + box-sizing: border-box; 25 31 } 26 32 27 33 body { ··· 32 38 line-height: 1.5; 33 39 margin: auto; 34 40 text-align: center; 35 - max-width: 600px; 41 + max-width: 900px; 36 42 } 37 43 38 44 h1 { 39 45 font-weight: 700; 40 46 letter-spacing: -1px; 41 47 margin-bottom: 8px; 48 + font-size: 2.2rem; 42 49 } 43 50 44 51 p { ··· 49 56 a { 50 57 color: var(--link-color); 51 58 text-decoration: none; 59 + transition: color 0.2s ease; 52 60 } 53 61 54 62 a:hover { 55 63 text-decoration: underline; 64 + color: #ffd9d9; 65 + } 66 + 67 + /* --- STATS GRID --- */ 68 + .stats-grid { 69 + display: grid; 70 + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); 71 + gap: 15px; 72 + margin: 30px 0; 73 + } 74 + 75 + .stat-card { 76 + background: linear-gradient(135deg, var(--stat-card-bg) 0%, var(--card-bg) 100%); 77 + border: 1px solid var(--border); 78 + border-radius: 12px; 79 + padding: 20px; 80 + text-align: center; 81 + transition: transform 0.2s ease, box-shadow 0.2s ease; 82 + position: relative; 83 + overflow: hidden; 84 + } 85 + 86 + .stat-card::before { 87 + content: ''; 88 + position: absolute; 89 + top: 0; 90 + left: 0; 91 + right: 0; 92 + height: 3px; 93 + background: linear-gradient(90deg, var(--link-color), rgba(255,204,204,0.3)); 94 + opacity: 0; 95 + transition: opacity 0.3s ease; 96 + } 97 + 98 + .stat-card:hover { 99 + transform: translateY(-5px); 100 + box-shadow: 0 8px 20px rgba(0,0,0,0.4); 101 + } 102 + 103 + .stat-card:hover::before { 104 + opacity: 1; 105 + } 106 + 107 + .stat-icon { 108 + font-size: 2rem; 109 + margin-bottom: 10px; 110 + opacity: 0.8; 111 + } 112 + 113 + .stat-value { 114 + font-size: 2rem; 115 + font-weight: 700; 116 + color: var(--text-color); 117 + margin: 5px 0; 118 + letter-spacing: -1px; 119 + } 120 + 121 + .stat-label { 122 + font-size: 0.85rem; 123 + color: var(--subtext-color); 124 + text-transform: uppercase; 125 + letter-spacing: 0.5px; 126 + font-weight: 600; 127 + } 128 + 129 + .stat-loading { 130 + opacity: 0.5; 56 131 } 57 132 58 133 /* --- UPLOADER STYLING --- */ 59 134 .upload-card { 60 135 background-color: var(--card-bg); 61 136 border: 1px solid var(--border); 62 - border-radius: 12px; 63 - padding: 30px; 137 + border-radius: 16px; 138 + padding: 35px; 64 139 margin: 40px auto; 65 - box-shadow: 0 4px 6px rgba(0,0,0,0.3); 140 + box-shadow: 0 6px 12px rgba(0,0,0,0.4); 66 141 } 67 142 68 143 .file-input-label { 69 144 display: block; 70 145 border: 2px dashed var(--border); 71 146 border-radius: 12px; 72 - padding: 40px 20px; 147 + padding: 50px 20px; 73 148 cursor: pointer; 74 - transition: all 0.2s ease; 149 + transition: all 0.3s ease; 75 150 color: var(--subtext-color); 151 + background: rgba(0,0,0,0.2); 76 152 } 77 153 78 154 .file-input-label:hover { 79 155 border-color: var(--link-color); 80 - background: rgba(255,255,255,0.02); 156 + background: rgba(255,255,255,0.03); 157 + transform: scale(1.01); 158 + } 159 + 160 + .file-input-label.drag-over { 161 + border-color: var(--success-green); 162 + background: rgba(52, 199, 89, 0.05); 163 + transform: scale(1.02); 81 164 } 82 165 83 166 .file-input-label i { 84 - font-size: 2rem; 85 - margin-bottom: 10px; 167 + font-size: 2.5rem; 168 + margin-bottom: 15px; 86 169 display: block; 170 + opacity: 0.7; 87 171 } 88 172 89 173 #file-input { 90 174 display: none; 91 175 } 92 176 177 + #file-name { 178 + display: block; 179 + margin-top: 10px; 180 + font-size: 1rem; 181 + font-weight: 500; 182 + } 183 + 184 + .file-info { 185 + margin-top: 15px; 186 + padding: 12px; 187 + background: var(--post-bg); 188 + border-radius: 8px; 189 + border: 1px solid var(--border); 190 + display: none; 191 + } 192 + 193 + .file-info.show { 194 + display: block; 195 + } 196 + 197 + .file-detail { 198 + font-size: 0.85rem; 199 + color: var(--subtext-color); 200 + margin: 5px 0; 201 + } 202 + 93 203 button { 94 - background: var(--text-color); 204 + background: linear-gradient(135deg, #ffffff 0%, #f0f0f0 100%); 95 205 color: #000000; 96 206 border: none; 97 - padding: 12px 24px; 207 + padding: 14px 28px; 98 208 border-radius: 999px; 99 209 font-weight: 600; 100 210 margin-top: 20px; 101 211 cursor: pointer; 102 212 width: 100%; 103 - transition: transform 0.1s ease; 213 + transition: all 0.2s ease; 214 + font-size: 1rem; 215 + box-shadow: 0 2px 8px rgba(255,255,255,0.1); 104 216 } 105 217 106 218 button:hover { 107 219 transform: translateY(-2px); 220 + box-shadow: 0 4px 12px rgba(255,255,255,0.2); 108 221 } 109 222 110 223 button:active { ··· 114 227 button:disabled { 115 228 opacity: 0.5; 116 229 cursor: not-allowed; 230 + transform: none; 231 + } 232 + 233 + /* --- PROGRESS BAR --- */ 234 + .progress-container { 235 + margin-top: 15px; 236 + display: none; 237 + } 238 + 239 + .progress-container.show { 240 + display: block; 241 + } 242 + 243 + .progress-bar { 244 + width: 100%; 245 + height: 8px; 246 + background: var(--post-bg); 247 + border-radius: 999px; 248 + overflow: hidden; 249 + border: 1px solid var(--border); 250 + } 251 + 252 + .progress-fill { 253 + height: 100%; 254 + background: linear-gradient(90deg, var(--link-color), var(--success-green)); 255 + width: 0%; 256 + transition: width 0.3s ease; 257 + border-radius: 999px; 117 258 } 118 259 119 260 /* --- RESULT AREA --- */ ··· 122 263 display: none; 123 264 text-align: left; 124 265 background: var(--post-bg); 125 - padding: 15px; 126 - border-radius: 8px; 127 - word-break: break-all; 128 - border: 1px solid var(--border); 266 + padding: 20px; 267 + border-radius: 12px; 268 + border: 1px solid var(--success-green); 269 + animation: slideIn 0.3s ease; 270 + } 271 + 272 + @keyframes slideIn { 273 + from { 274 + opacity: 0; 275 + transform: translateY(-10px); 276 + } 277 + to { 278 + opacity: 1; 279 + transform: translateY(0); 280 + } 281 + } 282 + 283 + #result.show { 284 + display: block; 129 285 } 130 286 131 287 #result small { 132 288 color: var(--subtext-color); 289 + font-weight: 600; 290 + text-transform: uppercase; 291 + font-size: 0.75rem; 292 + letter-spacing: 0.5px; 133 293 } 134 294 135 295 #url-text { 136 - margin: 5px 0; 137 - font-family: monospace; 296 + margin: 10px 0; 297 + font-family: 'Monaco', 'Courier New', monospace; 138 298 font-size: 0.9rem; 299 + padding: 12px; 300 + background: rgba(0,0,0,0.3); 301 + border-radius: 6px; 302 + border: 1px solid var(--border); 303 + word-break: break-all; 139 304 } 140 305 141 306 .copy-btn { 142 - background: rgba(255,255,255,0.04); 307 + background: rgba(255,255,255,0.06); 143 308 color: var(--link-color); 144 309 border: 1px solid var(--border); 145 310 font-size: 0.9rem; 146 - padding: 8px 14px; 311 + padding: 10px 16px; 147 312 width: auto; 148 313 margin-top: 10px; 314 + display: inline-flex; 315 + align-items: center; 316 + gap: 8px; 149 317 } 150 318 151 319 .copy-btn:hover { 152 - background: rgba(255,255,255,0.08); 320 + background: rgba(255,255,255,0.1); 153 321 border-color: var(--link-color); 154 322 } 155 323 156 324 hr { 157 325 border: none; 158 326 border-top: 1px solid var(--border); 159 - margin: 30px 0; 327 + margin: 40px 0; 160 328 } 161 329 162 330 .status-msg { 163 - margin-top: 10px; 164 - font-size: 0.9rem; 165 - color: var(--link-color); 331 + margin-top: 15px; 332 + font-size: 0.95rem; 333 + color: var(--link-color); 334 + font-weight: 500; 166 335 } 167 336 168 337 /* --- SOCIAL BUTTONS --- */ 169 338 .social-row { 170 339 display: flex; 171 - gap: 10px; 340 + gap: 12px; 172 341 flex-wrap: wrap; 173 - margin: 12px 0 20px 0; 342 + margin: 15px 0 20px 0; 174 343 justify-content: center; 175 344 } 176 345 ··· 179 348 align-items: center; 180 349 justify-content: center; 181 350 gap: 8px; 182 - padding: 8px 14px; 351 + padding: 10px 16px; 183 352 border-radius: 999px; 184 353 background: rgba(255,255,255,0.04); 185 354 color: var(--text-color); ··· 195 364 background: rgba(255,255,255,0.08); 196 365 transform: translateY(-2px); 197 366 box-shadow: 0 4px 12px rgba(0,0,0,0.3); 367 + text-decoration: none; 198 368 } 199 369 200 370 .social-btn i { ··· 205 375 206 376 .social-btn .label { 207 377 display: inline-block; 208 - opacity: 1; 209 - transform: translateX(0); 210 - margin-left: 8px; 211 378 white-space: nowrap; 212 - color: inherit; 213 379 font-weight: 600; 214 380 font-size: 0.95rem; 215 - max-width: 180px; 216 - overflow: hidden; 217 - vertical-align: middle; 218 381 } 219 382 220 - #file-name { 221 - display: block; 222 - margin-top: 8px; 383 + /* --- FOOTER --- */ 384 + #site-footer { 385 + font-size: 0.85rem; 386 + color: var(--subtext-color); 387 + padding: 20px 0; 388 + } 389 + 390 + /* --- RESPONSIVE --- */ 391 + @media (max-width: 600px) { 392 + .stats-grid { 393 + grid-template-columns: repeat(2, 1fr); 394 + } 395 + 396 + h1 { 397 + font-size: 1.8rem; 398 + } 399 + 400 + .stat-value { 401 + font-size: 1.5rem; 402 + } 223 403 } 224 404 </style> 225 405 </head> 226 406 <body> 227 407 228 - <h1>MBD CDN</h1> 408 + <h1><i class="fa-solid fa-database" style="color: #ffffff;"></i> MBD CDN</h1> 229 409 <p> 230 410 The MBD CDN is a network of servers located around the world powered by the Cloudflare global network. 231 411 <br> 232 - It's designed to deliver media <i>(images, videos, live broadcasts, etc)</i> at extremely fast speeds with 100% uptime 412 + It's designed to deliver media <i>(images, videos, live broadcasts, etc)</i> at extremely fast speeds with 100% uptime. 233 413 </p> 234 414 415 + <!-- Stats Cards --> 416 + <div class="stats-grid"> 417 + <div class="stat-card"> 418 + <div class="stat-icon"><i class="fa-regular fa-image"></i></div> 419 + <div class="stat-value stat-loading" id="stat-images">--</div> 420 + <div class="stat-label">Images</div> 421 + </div> 422 + <div class="stat-card"> 423 + <div class="stat-icon"><i class="fa-solid fa-video"></i></div> 424 + <div class="stat-value stat-loading" id="stat-videos">--</div> 425 + <div class="stat-label">Videos</div> 426 + </div> 427 + <div class="stat-card"> 428 + <div class="stat-icon"><i class="fa-solid fa-photo-film"></i></div> 429 + <div class="stat-value stat-loading" id="stat-gifs">--</div> 430 + <div class="stat-label">GIFs</div> 431 + </div> 432 + <div class="stat-card"> 433 + <div class="stat-icon"><i class="fa-solid fa-database"></i></div> 434 + <div class="stat-value stat-loading" id="stat-storage">--</div> 435 + <div class="stat-label">Storage Used</div> 436 + </div> 437 + </div> 438 + 439 + <!-- Upload Card --> 235 440 <div class="upload-card"> 236 441 <label for="file-input" class="file-input-label" id="drop-zone"> 237 442 <span id="file-name">Click to select or drag file here</span> 238 443 </label> 239 444 <input type="file" id="file-input"> 240 445 241 - <button id="upload-btn">Upload to MBD CDN <i class="fa-solid fa-cloud-arrow-up"></i></button> 446 + <div class="file-info" id="file-info"> 447 + <div class="file-detail"><strong>File:</strong> <span id="detail-name"></span></div> 448 + <div class="file-detail"><strong>Size:</strong> <span id="detail-size"></span></div> 449 + <div class="file-detail"><strong>Type:</strong> <span id="detail-type"></span></div> 450 + </div> 451 + 452 + <div class="progress-container" id="progress-container"> 453 + <div class="progress-bar"> 454 + <div class="progress-fill" id="progress-fill"></div> 455 + </div> 456 + </div> 457 + 458 + <button id="upload-btn"> 459 + <i class="fa-solid fa-cloud-arrow-up"></i> Upload to MBD CDN 460 + </button> 242 461 <div id="status" class="status-msg"></div> 243 462 244 463 <div id="result"> 245 - <small>Public URL:</small> 464 + <small>✅ Public URL:</small> 246 465 <div id="url-text"></div> 247 - <button class="copy-btn" onclick="copyUrl()">Copy URL</button> 466 + <button class="copy-btn" onclick="copyUrl()"> 467 + <i class="fa-solid fa-copy"></i> Copy URL 468 + </button> 248 469 </div> 249 470 </div> 250 471 251 472 <hr> 252 - <p><b>Social Links:</b></p> 473 + <p><b>Quick Links:</b></p> 253 474 <div id="social-links"></div> 254 475 <hr> 255 476 <div id="site-footer"></div> ··· 263 484 const result = document.getElementById('result'); 264 485 const urlText = document.getElementById('url-text'); 265 486 const dropZone = document.getElementById('drop-zone'); 487 + const fileInfo = document.getElementById('file-info'); 488 + const progressContainer = document.getElementById('progress-container'); 489 + const progressFill = document.getElementById('progress-fill'); 490 + 491 + // Format bytes to human readable 492 + function formatBytes(bytes) { 493 + if (bytes === 0) return '0 Bytes'; 494 + const k = 1024; 495 + const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']; 496 + const i = Math.floor(Math.log(bytes) / Math.log(k)); 497 + return Math.round((bytes / Math.pow(k, i)) * 100) / 100 + ' ' + sizes[i]; 498 + } 499 + 500 + // Format large numbers 501 + function formatNumber(num) { 502 + return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); 503 + } 504 + 505 + // Load statistics 506 + async function loadStats() { 507 + try { 508 + const response = await fetch('https://cdn.madebydanny.uk/stats'); 509 + const data = await response.json(); 510 + 511 + if (data.success) { 512 + document.getElementById('stat-images').innerText = formatNumber(data.stats.images); 513 + document.getElementById('stat-videos').innerText = formatNumber(data.stats.videos); 514 + document.getElementById('stat-gifs').innerText = formatNumber(data.stats.gifs); 515 + document.getElementById('stat-storage').innerText = formatBytes(data.stats.totalSize); 516 + 517 + // Remove loading state 518 + document.querySelectorAll('.stat-value').forEach(el => { 519 + el.classList.remove('stat-loading'); 520 + }); 521 + } 522 + } catch (err) { 523 + console.error('Failed to load stats:', err); 524 + document.querySelectorAll('.stat-value').forEach(el => { 525 + el.innerText = '—'; 526 + el.classList.remove('stat-loading'); 527 + }); 528 + } 529 + } 530 + 531 + // Load stats on page load 532 + loadStats(); 266 533 267 534 // Update UI when file selected 268 535 fileInput.addEventListener('change', () => { 269 536 if (fileInput.files.length > 0) { 270 - fileNameDisp.innerText = fileInput.files[0].name; 537 + const file = fileInput.files[0]; 538 + fileNameDisp.innerText = file.name; 539 + 540 + // Show file info 541 + document.getElementById('detail-name').innerText = file.name; 542 + document.getElementById('detail-size').innerText = formatBytes(file.size); 543 + document.getElementById('detail-type').innerText = file.type || 'Unknown'; 544 + fileInfo.classList.add('show'); 271 545 } 272 546 }); 273 547 274 548 // Drag and drop support 275 549 dropZone.addEventListener('dragover', (e) => { 276 550 e.preventDefault(); 277 - dropZone.style.borderColor = 'var(--link-color)'; 278 - dropZone.style.background = 'rgba(255,255,255,0.02)'; 551 + dropZone.classList.add('drag-over'); 279 552 }); 280 553 281 554 dropZone.addEventListener('dragleave', (e) => { 282 555 e.preventDefault(); 283 - dropZone.style.borderColor = ''; 284 - dropZone.style.background = ''; 556 + dropZone.classList.remove('drag-over'); 285 557 }); 286 558 287 559 dropZone.addEventListener('drop', (e) => { 288 560 e.preventDefault(); 289 - dropZone.style.borderColor = ''; 290 - dropZone.style.background = ''; 561 + dropZone.classList.remove('drag-over'); 291 562 292 563 if (e.dataTransfer.files.length > 0) { 293 564 fileInput.files = e.dataTransfer.files; 294 - fileNameDisp.innerText = e.dataTransfer.files[0].name; 565 + const file = e.dataTransfer.files[0]; 566 + fileNameDisp.innerText = file.name; 567 + 568 + // Show file info 569 + document.getElementById('detail-name').innerText = file.name; 570 + document.getElementById('detail-size').innerText = formatBytes(file.size); 571 + document.getElementById('detail-type').innerText = file.type || 'Unknown'; 572 + fileInfo.classList.add('show'); 295 573 } 296 574 }); 297 575 298 576 uploadBtn.addEventListener('click', async () => { 299 577 if (fileInput.files.length === 0) { 300 - status.innerText = "Please select a file first."; 578 + status.innerText = "⚠️ Please select a file first."; 301 579 status.style.color = 'var(--error-red)'; 302 580 return; 303 581 } 304 582 305 583 const file = fileInput.files[0]; 306 584 uploadBtn.disabled = true; 307 - uploadBtn.innerText = "Uploading..."; 585 + uploadBtn.innerHTML = '<i class="fa-solid fa-spinner fa-spin"></i> Uploading...'; 308 586 status.innerText = ""; 309 - result.style.display = 'none'; 587 + result.classList.remove('show'); 588 + progressContainer.classList.add('show'); 589 + progressFill.style.width = '0%'; 590 + 591 + // Simulate progress 592 + let progress = 0; 593 + const progressInterval = setInterval(() => { 594 + progress += Math.random() * 15; 595 + if (progress > 90) progress = 90; 596 + progressFill.style.width = progress + '%'; 597 + }, 200); 310 598 311 599 try { 312 - // Point this to your Worker URL 313 600 const response = await fetch('https://cdn.madebydanny.uk', { 314 601 method: 'POST', 315 602 body: file, ··· 318 605 } 319 606 }); 320 607 608 + clearInterval(progressInterval); 609 + progressFill.style.width = '100%'; 610 + 321 611 const data = await response.json(); 322 612 323 613 if (data.success) { 324 - result.style.display = 'block'; 614 + result.classList.add('show'); 325 615 urlText.innerText = data.url; 326 616 status.style.color = 'var(--success-green)'; 327 - status.innerText = "Upload successful!"; 617 + status.innerText = "✅ Upload successful!"; 618 + 619 + // Reload stats 620 + setTimeout(() => loadStats(), 500); 621 + 622 + // Reset form after 3 seconds 623 + setTimeout(() => { 624 + fileInput.value = ''; 625 + fileNameDisp.innerText = 'Click to select or drag file here'; 626 + fileInfo.classList.remove('show'); 627 + progressContainer.classList.remove('show'); 628 + }, 3000); 328 629 } else { 329 630 throw new Error(data.error || "Upload failed"); 330 631 } 331 632 } catch (err) { 633 + clearInterval(progressInterval); 634 + progressContainer.classList.remove('show'); 332 635 status.style.color = 'var(--error-red)'; 333 - status.innerText = "Error: " + err.message; 636 + status.innerText = "❌ Error: " + err.message; 334 637 } finally { 335 638 uploadBtn.disabled = false; 336 - uploadBtn.innerText = "Upload to R2"; 639 + uploadBtn.innerHTML = '<i class="fa-solid fa-cloud-arrow-up"></i> Upload to MBD CDN'; 337 640 } 338 641 }); 339 642 340 643 function copyUrl() { 341 644 navigator.clipboard.writeText(urlText.innerText); 342 645 const copyBtn = document.querySelector('.copy-btn'); 343 - const originalText = copyBtn.innerText; 344 - copyBtn.innerText = "Copied!"; 646 + const originalHTML = copyBtn.innerHTML; 647 + copyBtn.innerHTML = '<i class="fa-solid fa-check"></i> Copied!'; 648 + copyBtn.style.background = 'var(--success-green)'; 649 + copyBtn.style.color = '#000'; 345 650 setTimeout(() => { 346 - copyBtn.innerText = originalText; 651 + copyBtn.innerHTML = originalHTML; 652 + copyBtn.style.background = ''; 653 + copyBtn.style.color = ''; 347 654 }, 2000); 348 655 } 349 656 </script>