ai-infrastructure-hugg…
Hugging Face Inference SDK patterns for TypeScript/Node.js — InferenceClient setup, chat completion, text generation, streaming, embeddings, image generation,…
File upload patterns - drag-drop dropzones, chunked and resumable uploads, presigned URL flows, file validation (MIME type, magic bytes), progress tracking, accessibility (ARIA)
$ npx -y skills add agents-inc/skills --skill web-files-file-upload-patterns --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/web-files-file-upload-patternsContext preview
The summary Claude sees to decide when to auto-load this skill.
File upload patterns - drag-drop dropzones, chunked and resumable uploads, presigned URL flows, file validation (MIME type, magic bytes), progress tracking, accessibility (ARIA)
name: web-files-file-upload-patterns description: File upload patterns - drag-drop dropzones, chunked and resumable uploads, presigned URL flows, file validation (MIME type, magic bytes), progress tracking, accessibility (ARIA)
> **Quick Guide:** A dropzone is a keyboard-operable button wrapping a hidden file input, with drag > as an enhancement. Validate for the user's benefit on the client — extension, MIME type, then the > file's own magic bytes — and again on the server, because none of the client checks are security. > Progress needs `XMLHttpRequest`; `fetch` has no upload progress event. Past roughly 100MB, chunk > the file so a failure costs one chunk. Large files go straight to storage on a presigned URL the > server issues, so no request body is ever proxied.
**Detailed Resources:**
---
The destination decides almost everything else.
cap the server can enforce. [examples/core.md](examples/core.md) and [examples/progress.md](examples/progress.md) are the whole of it.
it directly, so no bytes pass through your application. [examples/presigned-upload.md](examples/presigned-upload.md).
limit, and record which parts landed so a retry resumes. [examples/resumable.md](examples/resumable.md).
---
<critical_requirements>
**Validate on the server as well as in the browser.** Client validation exists to tell the user quickly what will be rejected; anyone can skip it entirely, so it settles nothing about safety.
**Read the file's first bytes when the type matters.** Extensions and MIME types are both supplied by whoever made the file, and a renamed executable passes every check that trusts them.
**Revoke every object URL you create.** A preview holds the whole file in memory until `URL.revokeObjectURL()` runs, so a user who changes their mind three times leaks three files.
**Make the dropzone reachable from the keyboard.** `role="button"`, `tabIndex={0}` and an Enter/Space handler that opens the file dialog, with drag layered on top — mobile has no drag at all, so the click path is the real one.
**Have the server issue a short-lived presigned URL rather than proxying the body.** The upload then costs your application nothing, and no storage credential is ever in reach of the browser.
</critical_requirements>
---
**Auto-detection:** dropzone, dataTransfer.files, dragenter, dragleave, dragover, input type="file", event.target.files, accept attribute, xhr.upload.addEventListener, lengthComputable, presigned URL, uploadUrl, multipart upload, UploadPart, ETag, chunked upload, file.slice, Content-Range, resumable upload, tus, Tus-Resumable, Upload-Offset, magic bytes, file signature, FormData append file
**Applies to:**
**Handled elsewhere:**
given
---
<philosophy>
An upload is three independent problems that get conflated: choosing a file, checking it, and moving its bytes. Keeping them separate is what makes any of them replaceable.
The checking half has a rule that never bends. **Client validation is a user-experience feature, and the server's is the only one that is a control.** Everything the browser knows about a file — its name, its extension, its `type` — came from the file itself. Reading magic bytes raises the bar but does not change the category: it is still a check the client can be made to skip.
The moving half scales by a different axis: not how many files, but how long a single request is open. A short request can fail and be retried whole. A long one accumulates the probability of a dropped connection until retrying whole is unacceptable, and that is the point at which chunking starts paying for its complexity — not at a particular byte count.
</philosophy>
---
<patterns>
Count drag events rather than tracking a boolean. `dragenter` and `dragleave` fire for every nested element, so a boolean flickers off the moment the pointer crosses a child.
The official skills marketplace for Agents Inc. 150+ skills covering everything from React and Prisma to Redis, ElevenLabs, and infrastructure tooling. Pick the skills that match your stack and install them via Claude Code. Need more control?
Repo: agents-inc/skills
Hugging Face Inference SDK patterns for TypeScript/Node.js — InferenceClient setup, chat completion, text generation, streaming, embeddings, image generation,…
LiteLLM proxy server setup, TypeScript client patterns via OpenAI SDK, model routing, fallbacks, load balancing, spend tracking, virtual keys, and production…
Serverless GPU compute platform for AI model deployment — web endpoints, GPU functions, model serving, and TypeScript client patterns
Local LLM inference with the Ollama JavaScript client -- chat, streaming, tool calling, vision, embeddings, structured output, model management, and…
Replicate SDK patterns for TypeScript/Node.js -- client setup, predictions, streaming, webhooks, file handling, model versioning, deployments, and training
Together AI SDK patterns for TypeScript — client setup, chat completions, streaming, structured output, function calling, embeddings, image generation,…