docs.html (23327B)
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>Docs · Upload Hub</title> 7 <link rel="preconnect" href="https://fonts.googleapis.com"> 8 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> 9 <link href="https://fonts.googleapis.com/css2?family=Lexend:wght@300;400;500;600;700&display=swap" rel="stylesheet"> 10 <link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,400,1,0" rel="stylesheet" /> 11 <script src="https://cdn.tailwindcss.com"></script> 12 <script> 13 tailwind.config = { 14 theme: { 15 extend: { 16 fontFamily: { sans: ['Lexend', 'sans-serif'] }, 17 colors: { 18 m3: { 19 background: '#FDFCFB', backgroundDark: '#1A1C19', 20 surfaceContainer: '#F1F1EA', surfaceContainerDark: '#2D2F2B', 21 surfaceContainerHigh: '#EBEBE4', surfaceContainerHighDark: '#333531', 22 surfaceContainerHighest: '#E5E6DE', surfaceContainerHighestDark: '#434541', 23 onSurface: '#1A1C19', onSurfaceDark: '#E3E3DC', 24 onSurfaceVariant: '#43483E', onSurfaceVariantDark: '#C3C8BC', 25 primary: '#386A20', primaryDark: '#9CD67D', 26 onPrimary: '#FFFFFF', onPrimaryDark: '#0C3900', 27 secondaryContainer: '#D7E8CD', secondaryContainerDark: '#374B2E', 28 onSecondaryContainer: '#111F0F', onSecondaryContainerDark: '#D7E8CD', 29 outline: '#74796D', outlineDark: '#8D9286', 30 } 31 } 32 } 33 } 34 } 35 </script> 36 <style> 37 body { background-color: #FDFCFB; margin: 0; -webkit-font-smoothing: antialiased; } 38 @media (prefers-color-scheme: dark) { body { background-color: #1A1C19; } } 39 40 .diagram-box { background: #F1F1EA; } 41 @media (prefers-color-scheme: dark) { .diagram-box { background: #2D2F2B; } } 42 43 .node { fill: #D7E8CD; stroke: #386A20; } 44 @media (prefers-color-scheme: dark) { .node { fill: #374B2E; stroke: #9CD67D; } } 45 46 .node-alt { fill: #E5E6DE; stroke: #74796D; } 47 @media (prefers-color-scheme: dark) { .node-alt { fill: #434541; stroke: #8D9286; } } 48 49 .arrow { stroke: #74796D; stroke-width: 2; fill: none; marker-end: url(#arrowhead); } 50 @media (prefers-color-scheme: dark) { .arrow { stroke: #8D9286; } } 51 52 .arrow-label { fill: #43483E; font-family: 'Lexend', sans-serif; font-size: 10px; } 53 @media (prefers-color-scheme: dark) { .arrow-label { fill: #C3C8BC; } } 54 55 code { background: #E5E6DE; padding: 2px 6px; border-radius: 4px; font-size: 0.85em; } 56 @media (prefers-color-scheme: dark) { code { background: #434541; } } 57 </style> 58 </head> 59 <body class="bg-m3-background dark:bg-m3-backgroundDark text-m3-onSurface dark:text-m3-onSurfaceDark font-sans"> 60 <div class="max-w-[720px] mx-auto px-4 py-10"> 61 <a href="https://uploads.amit.is-a.dev" class="inline-flex items-center gap-1 text-sm font-semibold text-m3-primary dark:text-m3-primaryDark mb-6"> 62 <span class="material-symbols-outlined text-[18px]">arrow_back</span> Back to Upload 63 </a> 64 <h1 class="text-3xl font-bold tracking-tight mb-2">How this tool works</h1> 65 <p class="text-m3-onSurfaceVariant dark:text-m3-onSurfaceVariantDark mb-10"> 66 A permanent, free file host built on a Hugging Face dataset repo, served through a serverless 67 FastAPI backend on Vercel. Here's exactly what happens behind each button. 68 </p> 69 70 <!-- ===================== Section: Architecture ===================== --> 71 <section class="mb-14"> 72 <h2 class="text-xl font-bold mb-3">1. The building blocks</h2> 73 <p class="text-sm leading-relaxed text-m3-onSurfaceVariant dark:text-m3-onSurfaceVariantDark mb-4"> 74 There are three pieces: the <strong>frontend</strong> (this website, plain HTML/JS), the 75 <strong>backend</strong> (a Python FastAPI app running as a Vercel serverless function), and 76 <strong>storage</strong> (a public Hugging Face dataset repo, which gives ~unlimited free storage 77 and a permanent, directly-linkable URL per file). 78 </p> 79 <div class="diagram-box rounded-[20px] p-4 overflow-x-auto"> 80 <svg viewBox="0 0 680 140" xmlns="http://www.w3.org/2000/svg" class="min-w-[600px]"> 81 <defs> 82 <marker id="arrowhead" markerWidth="8" markerHeight="8" refX="7" refY="4" orient="auto"> 83 <path d="M0,0 L8,4 L0,8 Z" class="node-alt" /> 84 </marker> 85 </defs> 86 87 <rect x="20" y="45" width="150" height="50" rx="12" class="node-alt"/> 88 <foreignObject x="20" y="45" width="150" height="50"> 89 <div xmlns="http://www.w3.org/1999/xhtml" class="w-full h-full flex flex-col items-center justify-center text-center px-1 text-[12px] font-medium text-m3-onSurface dark:text-m3-onSurfaceDark leading-tight"> 90 Browser 91 <span class="text-[10px] opacity-80 font-normal">index.html</span> 92 </div> 93 </foreignObject> 94 95 <rect x="265" y="45" width="150" height="50" rx="12" class="node"/> 96 <foreignObject x="265" y="45" width="150" height="50"> 97 <div xmlns="http://www.w3.org/1999/xhtml" class="w-full h-full flex flex-col items-center justify-center text-center px-1 text-[12px] font-semibold text-m3-onSecondaryContainer dark:text-m3-onSecondaryContainerDark leading-tight"> 98 FastAPI backend 99 <span class="text-[10px] opacity-80 font-normal">index.py (Vercel)</span> 100 </div> 101 </foreignObject> 102 103 <rect x="510" y="45" width="150" height="50" rx="12" class="node-alt"/> 104 <foreignObject x="510" y="45" width="150" height="50"> 105 <div xmlns="http://www.w3.org/1999/xhtml" class="w-full h-full flex flex-col items-center justify-center text-center px-1 text-[12px] font-medium text-m3-onSurface dark:text-m3-onSurfaceDark leading-tight"> 106 HF Dataset 107 <span class="text-[10px] opacity-80 font-normal">notamitgamer/uploads</span> 108 </div> 109 </foreignObject> 110 111 <path d="M170,65 L265,65" class="arrow"/> 112 <text x="217" y="55" text-anchor="middle" class="arrow-label">HTTP request</text> 113 114 <path d="M415,65 L510,65" class="arrow"/> 115 <text x="462" y="55" text-anchor="middle" class="arrow-label">HF API</text> 116 </svg> 117 </div> 118 </section> 119 120 <!-- ===================== Section: Regular upload ===================== --> 121 <section class="mb-14"> 122 <h2 class="text-xl font-bold mb-3">2. Uploading a file</h2> 123 <p class="text-sm leading-relaxed text-m3-onSurfaceVariant dark:text-m3-onSurfaceVariantDark mb-4"> 124 Drop a file (or several, or paste one) and the browser sends it straight to <code>/api/upload</code> 125 as <code>multipart/form-data</code>. No file ever touches disk on the server — it's read into memory 126 and streamed directly to Hugging Face. 127 </p> 128 <div class="diagram-box rounded-[20px] p-4 overflow-x-auto mb-4"> 129 <svg viewBox="0 0 680 250" xmlns="http://www.w3.org/2000/svg" class="min-w-[600px]"> 130 <rect x="20" y="10" width="200" height="40" rx="10" class="node-alt"/> 131 <foreignObject x="20" y="10" width="200" height="40"> 132 <div xmlns="http://www.w3.org/1999/xhtml" class="w-full h-full flex flex-col items-center justify-center text-center px-2 text-[12px] font-medium text-m3-onSurface dark:text-m3-onSurfaceDark leading-tight"> 133 Select / drop / paste file(s) 134 </div> 135 </foreignObject> 136 <path d="M120,50 L120,80" class="arrow"/> 137 138 <rect x="20" y="80" width="200" height="40" rx="10" class="node-alt"/> 139 <foreignObject x="20" y="80" width="200" height="40"> 140 <div xmlns="http://www.w3.org/1999/xhtml" class="w-full h-full flex flex-col items-center justify-center text-center px-2 text-[12px] font-medium text-m3-onSurface dark:text-m3-onSurfaceDark leading-tight"> 141 POST /api/upload 142 </div> 143 </foreignObject> 144 <path d="M120,120 L120,150" class="arrow"/> 145 146 <rect x="20" y="150" width="200" height="50" rx="10" class="node"/> 147 <foreignObject x="20" y="150" width="200" height="50"> 148 <div xmlns="http://www.w3.org/1999/xhtml" class="w-full h-full flex flex-col items-center justify-center text-center px-2 text-[12px] font-semibold text-m3-onSecondaryContainer dark:text-m3-onSecondaryContainerDark leading-tight"> 149 Sanitize custom_id 150 <span class="text-[10px] opacity-80 font-normal">or generate random ID</span> 151 </div> 152 </foreignObject> 153 <path d="M220,175 L340,175" class="arrow"/> 154 155 <rect x="340" y="155" width="200" height="40" rx="10" class="node"/> 156 <foreignObject x="340" y="155" width="200" height="40"> 157 <div xmlns="http://www.w3.org/1999/xhtml" class="w-full h-full flex flex-col items-center justify-center text-center px-2 text-[12px] font-semibold text-m3-onSecondaryContainer dark:text-m3-onSecondaryContainerDark leading-tight"> 158 Upload bytes to HF dataset 159 </div> 160 </foreignObject> 161 <path d="M440,195 L440,230 L120,230 L120,200" class="arrow"/> 162 <text x="280" y="225" text-anchor="middle" class="arrow-label">return link to browser</text> 163 </svg> 164 </div> 165 <ul class="text-sm leading-relaxed text-m3-onSurfaceVariant dark:text-m3-onSurfaceVariantDark list-disc pl-5 space-y-1"> 166 <li>Any file extension is accepted — the server never inspects file type, only reuses the extension for the generated ID.</li> 167 <li>Max size is <strong>~4.4 MB</strong> per file, kept just under Vercel's hard 4.5 MB request-body limit.</li> 168 <li>A custom ID is only allowed when uploading exactly one file, and is sanitized to block path traversal.</li> 169 </ul> 170 </section> 171 172 <!-- ===================== Section: Link serving ===================== --> 173 <section class="mb-14"> 174 <h2 class="text-xl font-bold mb-3">3. How links are served instantly</h2> 175 <p class="text-sm leading-relaxed text-m3-onSurfaceVariant dark:text-m3-onSurfaceVariantDark mb-4"> 176 Because all uploads are permanent, links are handled entirely by Vercel's static configuration 177 in <code>vercel.json</code>. The Python backend function is completely bypassed when you open a file. 178 </p> 179 <div class="diagram-box rounded-[20px] p-4 overflow-x-auto mb-4"> 180 <svg viewBox="0 0 680 180" xmlns="http://www.w3.org/2000/svg" class="min-w-[600px]"> 181 <rect x="240" y="10" width="200" height="40" rx="10" class="node-alt"/> 182 <foreignObject x="240" y="10" width="200" height="40"> 183 <div xmlns="http://www.w3.org/1999/xhtml" class="w-full h-full flex flex-col items-center justify-center text-center px-2 text-[12px] font-medium text-m3-onSurface dark:text-m3-onSurfaceDark leading-tight"> 184 Someone opens /<item_id> 185 </div> 186 </foreignObject> 187 <path d="M340,50 L340,80" class="arrow"/> 188 189 <rect x="240" y="80" width="200" height="40" rx="10" class="node"/> 190 <foreignObject x="240" y="80" width="200" height="40"> 191 <div xmlns="http://www.w3.org/1999/xhtml" class="w-full h-full flex flex-col items-center justify-center text-center px-2 text-[12px] font-semibold text-m3-onSecondaryContainer dark:text-m3-onSecondaryContainerDark leading-tight"> 192 vercel.json intercept 193 </div> 194 </foreignObject> 195 196 <path d="M340,120 L340,150" class="arrow"/> 197 <text x="390" y="140" text-anchor="middle" class="arrow-label">static redirect (instant)</text> 198 199 <rect x="240" y="150" width="200" height="30" rx="8" class="node-alt"/> 200 <foreignObject x="240" y="150" width="200" height="30"> 201 <div xmlns="http://www.w3.org/1999/xhtml" class="w-full h-full flex flex-col items-center justify-center text-center px-2 text-[12px] font-medium text-m3-onSurface dark:text-m3-onSurfaceDark leading-tight"> 202 File downloaded from HF 203 </div> 204 </foreignObject> 205 </svg> 206 </div> 207 <ul class="text-sm leading-relaxed text-m3-onSurfaceVariant dark:text-m3-onSurfaceVariantDark list-disc pl-5 space-y-1"> 208 <li>Since the python server never wakes up to process the link, cold-starts are completely eliminated.</li> 209 <li>Files are instantly redirected and served directly off Hugging Face's global CDN.</li> 210 </ul> 211 </section> 212 213 <!-- ===================== Section: Upload via URL ===================== --> 214 <section class="mb-14"> 215 <h2 class="text-xl font-bold mb-3">4. Uploading from a URL</h2> 216 <p class="text-sm leading-relaxed text-m3-onSurfaceVariant dark:text-m3-onSurfaceVariantDark mb-4"> 217 Instead of uploading from your device, you can hand the tool a link and have the server fetch 218 and re-host it — useful for backing up an image or file that's only temporarily available elsewhere. 219 </p> 220 <div class="diagram-box rounded-[20px] p-4 overflow-x-auto"> 221 <svg viewBox="0 0 680 100" xmlns="http://www.w3.org/2000/svg" class="min-w-[600px]"> 222 <rect x="10" y="30" width="150" height="40" rx="10" class="node-alt"/> 223 <foreignObject x="10" y="30" width="150" height="40"> 224 <div xmlns="http://www.w3.org/1999/xhtml" class="w-full h-full flex flex-col items-center justify-center text-center px-2 text-[12px] font-medium text-m3-onSurface dark:text-m3-onSurfaceDark leading-tight"> 225 You paste a URL 226 </div> 227 </foreignObject> 228 <path d="M160,50 L250,50" class="arrow"/> 229 230 <rect x="250" y="30" width="180" height="40" rx="10" class="node"/> 231 <foreignObject x="250" y="30" width="180" height="40"> 232 <div xmlns="http://www.w3.org/1999/xhtml" class="w-full h-full flex flex-col items-center justify-center text-center px-2 text-[12px] font-semibold text-m3-onSecondaryContainer dark:text-m3-onSecondaryContainerDark leading-tight"> 233 Backend fetches the URL 234 </div> 235 </foreignObject> 236 <path d="M430,50 L520,50" class="arrow"/> 237 238 <rect x="520" y="30" width="150" height="40" rx="10" class="node-alt"/> 239 <foreignObject x="520" y="30" width="150" height="40"> 240 <div xmlns="http://www.w3.org/1999/xhtml" class="w-full h-full flex flex-col items-center justify-center text-center px-2 text-[12px] font-medium text-m3-onSurface dark:text-m3-onSurfaceDark leading-tight"> 241 Uploaded to HF normally 242 </div> 243 </foreignObject> 244 </svg> 245 </div> 246 </section> 247 248 <!-- ===================== Section: Batch links ===================== --> 249 <section class="mb-14"> 250 <h2 class="text-xl font-bold mb-3">5. Batch links</h2> 251 <p class="text-sm leading-relaxed text-m3-onSurfaceVariant dark:text-m3-onSurfaceVariantDark mb-4"> 252 Upload more than one file at once and, alongside each file's own link, you also get a single 253 shareable <code>/batch/<id></code> link that opens a page listing every file from that upload. 254 </p> 255 <div class="diagram-box rounded-[20px] p-4 overflow-x-auto"> 256 <svg viewBox="0 0 680 180" xmlns="http://www.w3.org/2000/svg" class="min-w-[600px]"> 257 <rect x="20" y="20" width="200" height="40" rx="10" class="node-alt"/> 258 <foreignObject x="20" y="20" width="200" height="40"> 259 <div xmlns="http://www.w3.org/1999/xhtml" class="w-full h-full flex flex-col items-center justify-center text-center px-2 text-[12px] font-medium text-m3-onSurface dark:text-m3-onSurfaceDark leading-tight"> 260 Upload 3+ files together 261 </div> 262 </foreignObject> 263 <path d="M120,60 L120,90" class="arrow"/> 264 265 <rect x="20" y="90" width="200" height="50" rx="10" class="node"/> 266 <foreignObject x="20" y="90" width="200" height="50"> 267 <div xmlns="http://www.w3.org/1999/xhtml" class="w-full h-full flex flex-col items-center justify-center text-center px-2 text-[12px] font-semibold text-m3-onSecondaryContainer dark:text-m3-onSecondaryContainerDark leading-tight"> 268 Each file uploaded normally 269 <span class="text-[10px] opacity-80 font-normal">gets its own item_id</span> 270 </div> 271 </foreignObject> 272 <path d="M220,115 L340,115" class="arrow"/> 273 274 <rect x="340" y="90" width="200" height="50" rx="10" class="node"/> 275 <foreignObject x="340" y="90" width="200" height="50"> 276 <div xmlns="http://www.w3.org/1999/xhtml" class="w-full h-full flex flex-col items-center justify-center text-center px-2 text-[12px] font-semibold text-m3-onSecondaryContainer dark:text-m3-onSecondaryContainerDark leading-tight"> 277 Manifest written 278 <span class="text-[10px] opacity-80 font-normal">_batches/<batch_id>.json</span> 279 </div> 280 </foreignObject> 281 <path d="M540,115 L620,115 L620,150" class="arrow"/> 282 283 <rect x="510" y="150" width="150" height="30" rx="8" class="node-alt"/> 284 <foreignObject x="510" y="150" width="150" height="30"> 285 <div xmlns="http://www.w3.org/1999/xhtml" class="w-full h-full flex flex-col items-center justify-center text-center px-2 text-[10px] font-medium text-m3-onSurface dark:text-m3-onSurfaceDark leading-tight"> 286 /batch/<id> page 287 </div> 288 </foreignObject> 289 </svg> 290 </div> 291 </section> 292 293 <!-- ===================== Section: Limits table ===================== --> 294 <section class="mb-14"> 295 <h2 class="text-xl font-bold mb-3">6. Limits & behavior at a glance</h2> 296 <div class="bg-m3-surfaceContainer dark:bg-m3-surfaceContainerDark rounded-[16px] overflow-hidden text-sm"> 297 <div class="overflow-x-auto"> 298 <table class="w-full border-collapse min-w-[500px] sm:min-w-full"> 299 <tbody> 300 <tr class="border-b border-m3-surfaceContainerHighest dark:border-m3-surfaceContainerHighestDark"> 301 <td class="px-4 py-3 font-semibold align-top w-[140px] sm:w-1/3">Max file size</td> 302 <td class="px-4 py-3 text-m3-onSurfaceVariant dark:text-m3-onSurfaceVariantDark align-top">~4.4 MB per file (Vercel request-body limit)</td> 303 </tr> 304 <tr class="border-b border-m3-surfaceContainerHighest dark:border-m3-surfaceContainerHighestDark"> 305 <td class="px-4 py-3 font-semibold align-top">File types</td> 306 <td class="px-4 py-3 text-m3-onSurfaceVariant dark:text-m3-onSurfaceVariantDark align-top">Any extension, unrestricted</td> 307 </tr> 308 <tr class="border-b border-m3-surfaceContainerHighest dark:border-m3-surfaceContainerHighestDark"> 309 <td class="px-4 py-3 font-semibold align-top">Multiple files</td> 310 <td class="px-4 py-3 text-m3-onSurfaceVariant dark:text-m3-onSurfaceVariantDark align-top">Supported; each gets its own link + one shared batch link</td> 311 </tr> 312 <tr class="border-b border-m3-surfaceContainerHighest dark:border-m3-surfaceContainerHighestDark"> 313 <td class="px-4 py-3 font-semibold align-top">Custom ID</td> 314 <td class="px-4 py-3 text-m3-onSurfaceVariant dark:text-m3-onSurfaceVariantDark align-top">Single-file uploads only, sanitized to letters/numbers/dot/dash/underscore</td> 315 </tr> 316 <tr class="border-b border-m3-surfaceContainerHighest dark:border-m3-surfaceContainerHighestDark"> 317 <td class="px-4 py-3 font-semibold align-top">Deletion</td> 318 <td class="px-4 py-3 text-m3-onSurfaceVariant dark:text-m3-onSurfaceVariantDark align-top">Not supported by design</td> 319 </tr> 320 <tr class="border-b border-m3-surfaceContainerHighest dark:border-m3-surfaceContainerHighestDark"> 321 <td class="px-4 py-3 font-semibold align-top">Authentication</td> 322 <td class="px-4 py-3 text-m3-onSurfaceVariant dark:text-m3-onSurfaceVariantDark align-top">None — the tool is intentionally open</td> 323 </tr> 324 <tr> 325 <td class="px-4 py-3 font-semibold align-top">Storage</td> 326 <td class="px-4 py-3 text-m3-onSurfaceVariant dark:text-m3-onSurfaceVariantDark align-top">Public Hugging Face dataset repo</td> 327 </tr> 328 </tbody> 329 </table> 330 </div> 331 </div> 332 </section> 333 334 <a href="https://uploads.amit.is-a.dev" class="inline-flex items-center gap-1 text-sm font-semibold text-m3-primary dark:text-m3-primaryDark"> 335 <span class="material-symbols-outlined text-[18px]">arrow_back</span> Back to Upload 336 </a> 337 338 <div class="w-full text-center text-xs font-medium text-m3-outline dark:text-m3-outlineDark mt-10 mb-4"> 339 © 2026 <a href="https://github.com/notamitgamer">notamitgamer</a> 340 </div> 341 </div> 342 </body> 343 </html>