-
+
Upload
-
+
About
-
+
How it Works
-
+
+ Build
+
+
Limits
@@ -194,7 +197,7 @@
4
You get a public URL
-
A permanent cdn.madebydanny.uk link is returned instantly. Anyone with it can access the file, served from whichever Cloudflare PoP is closest to them.
+
A permanent cdn.danielmorrisey.com link is returned instantly. Anyone with it can access the file, served from whichever Cloudflare PoP is closest to them.
@@ -218,6 +221,36 @@
+
+
+
+
Build it into your app
+
The MBD CDN API is simple. Send a POST request with your file and get back a JSON response with your permanent URL.
+
+
+
+
POST Request
+
POST /api/upload HTTP/1.1
+Host: cdn.danielmorrisey.com
+Content-Type: application/octet-stream
+Content-Length: [file-size]
+
+[file-binary-data]
+
+
+
+
Response (200 OK)
+
{
+ "success": true,
+ "url": "https://cdn.danielmorrisey.com/uuid-filename.ext",
+ "filename": "uuid-filename.ext",
+ "size": 1024,
+ "type": "image/jpeg",
+ "timestamp": "2026-06-01T12:34:56.789Z"
+}
+
+
+
diff --git a/css/cdn.css b/css/cdn.css
index 9c31ff9..6680442 100644
--- a/css/cdn.css
+++ b/css/cdn.css
@@ -649,6 +649,44 @@ code {
}
.file-types strong { color: var(--text); }
+/* ── Code Blocks ── */
+
+.code-block {
+ margin: 1.5rem 0;
+ border: 1px solid var(--border);
+ border-radius: var(--radius);
+ background: var(--bg-card);
+ overflow: hidden;
+}
+
+.code-label {
+ font-family: var(--font-mono);
+ font-size: 0.75rem;
+ font-weight: 600;
+ text-transform: uppercase;
+ color: var(--text-dim);
+ background: var(--bg-raised);
+ padding: 0.5rem 1rem;
+ border-bottom: 1px solid var(--border);
+ letter-spacing: 0.05em;
+}
+
+.code-block pre {
+ margin: 0;
+ padding: 1rem;
+ overflow-x: auto;
+ font-family: var(--font-mono);
+ font-size: 0.8125rem;
+ line-height: 1.6;
+ color: var(--text-muted);
+}
+
+.code-block code {
+ background: none;
+ padding: 0;
+ color: inherit;
+}
+
/* ── Footer ── */
.site-footer {
diff --git a/js/cdn.js b/js/cdn.js
index 30decaa..606c84c 100644
--- a/js/cdn.js
+++ b/js/cdn.js
@@ -17,10 +17,19 @@ function switchTab(name, btn) {
document.querySelectorAll('.tab-pane').forEach(p => p.classList.remove('active'));
document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
document.getElementById('tab-' + name).classList.add('active');
- if (btn) btn.classList.add('active');
+ const button = btn || document.getElementById(name);
+ if (button) button.classList.add('active');
+ window.location.hash = name;
if (name === 'limits') loadLimits();
}
+function handleHashChange() {
+ const hash = window.location.hash.slice(1);
+ if (hash && ['upload', 'about', 'how', 'build', 'limits'].includes(hash)) {
+ switchTab(hash);
+ }
+}
+
// ── Stats ──────────────────────────────────────────────────────────
async function loadStats() {
@@ -231,4 +240,6 @@ function copyUrl() {
// ── Init ───────────────────────────────────────────────────────────
+window.addEventListener('hashchange', handleHashChange);
+if (window.location.hash) handleHashChange();
loadStats();