
Introduction
mediadrop is a headless, hooks-first file uploader for React with zero
runtime dependencies. It handles intake, drag/drop, validation, and upload
(queue, concurrency, retry, cancel) via a single useMediaDrop hook — the
same getRootProps/getInputProps shape you already know from
react-dropzone, with upload built in. No prebuilt widget — you own the
markup.
react-mediadrop ships at 4.4 KB minified + gzipped (per
); the
optional xhr-upload transport is a separate subpath import, so you only
pay for it if you use it.
Documentation and examples at .
Why
We built mediadrop for Autorender's own upload widget — the entry point for every file and media asset into our pipeline. It went through several iterations before it looked like this: a lightweight, hooks-first, headless core, with a pluggable transport layer instead of one fixed upload path.
What came out of it is a set of ordinary React primitives — hooks, validation, a transport contract — the same shape whether you're wiring them into a media pipeline or a plain upload form. We're open-sourcing mediadrop so any team building an uploader can start from the same primitives we did.
If you've used react-dropzone, the API will feel familiar —
useMediaDrop returns the same getRootProps/getInputProps shape, plus a
built-in upload queue react-dropzone doesn't have.
mediadrop is pre-1.0 (0.1.1), following semver — minor version bumps may
include breaking changes until 1.0. Full history in the
changelog [blocked].
Comparison
Closest to react-dropzone in API shape — useMediaDrop returns the same
getRootProps/getInputProps, plus the upload queue react-dropzone
doesn't have. Closest to Uppy in upload scope — a pluggable transport
contract instead of a plugin ecosystem — but without a dashboard,
Companion, or remote-provider import; see the
scope reference [blocked] for what's not
included.
Install
Using an AI coding agent? Also install the Agent Skill so it integrates the API correctly on the first try instead of guessing from the package name:
Also indexed on — reachable via MCP from Cursor, Claude Code, Windsurf, and other Context7-compatible tools with no local install.
- Ships as ESM with TypeScript types included — works with any modern bundler.
- Peer dependency on React 18+, nothing else.
- No
window/documentaccess at render time — safe to import in SSR frameworks (Next.js, Remix, etc.); browser APIs only run inside event handlers, on the client.
Quickstart
React
Upload (opt-in)
Without transport, nothing is uploaded — useMediaDrop only tracks
intake/validation state. See the
and for
the full API.
Blocks (shadcn registry)
Prebuilt, copy-into-your-project blocks — dropzone, avatar uploader, multi-file upload form, S3 direct-upload — installable via the shadcn CLI's support, no separate registry server required:
Swap dropzone for avatar-uploader, multi-file-upload-form, or
s3-direct-upload. (Shorter @mediadrop/dropzone form pending shadcn
Registry Directory review.)
What's implemented
Core: file intake from a picker or drag/drop, sync validation
(accept/maxFiles/minSize/maxSize + a custom validator), and drag
state (isDragActive/isDragAccept/isDragReject).
Upload (opt-in via transport): a pluggable transport contract, a queue
with concurrency limit + shared retry/backoff, cancel via AbortSignal, and
a reference react-mediadrop/xhr-upload transport.
Pause/resume, remote-provider import, OAuth, image transforms, a prebuilt widget, and any vendor-specific adapter are not implemented — see the scope reference [blocked] for the full, authoritative list.
Packages
Only react-mediadrop is published to npm — packages/core and
packages/xhr-upload are internal, workspace-only source packages bundled
directly into it at build time. skills/mediadrop is a separate
integration guide, not bundled into the package. Only react-mediadrop
matters if you're a consumer — the rest is listed here for contributors.
Example
examples/react-demo exercises react-mediadrop against a real backend
(examples/test-server, a plain Express app) instead of a faked dev-server
mock.
Open the demo, drop a file, hit "Upload all" — bytes land in
examples/test-server/uploads/ (git-ignored).
Commands
Support
Questions or issues not covered by the ? Open a or email .
Contributing
See CONTRIBUTING.md [blocked] before opening a PR.
License
Brought to you by , MIT [blocked]