# Deploy a drop box

> A small WeTransfer on your own bucket: drop a file, get a code, a link and a QR code, pick it up on any device until it expires, then burn it. A Next.js template built on s3nd, deployed to Vercel in one click.

Canonical: https://www.s3nd.sh/drop · Markdown: https://www.s3nd.sh/drop.md · Français: https://www.s3nd.sh/fr/drop

Drop a file, get an eight-character code, a link and a QR code; type the code or scan it on any device until it expires, then burn it. One Next.js app built on the library and the hooks, deployed to Vercel in one click with five environment variables.

- Deploy with Vercel: https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2FAbderrahmaneMouzoune%2Fs3nd%2Ftree%2Fmain%2Ftemplates%2Fdrop&project-name=s3nd-drop&repository-name=s3nd-drop&env=S3ND_BUCKET%2CS3ND_ENDPOINT%2CS3ND_REGION%2CAWS_ACCESS_KEY_ID%2CAWS_SECRET_ACCESS_KEY&envDescription=An+S3-compatible+bucket+and+a+key+pair+scoped+to+it.+R2%2C+S3%2C+MinIO%2C+Scaleway+and+Wasabi+all+work.&envLink=https%3A%2F%2Fwww.s3nd.sh%2Fproviders
- The template on GitHub: https://github.com/AbderrahmaneMouzoune/s3nd/tree/main/templates/drop
- Try it on drop.s3nd.sh: https://drop.s3nd.sh

## Two pages and one route.
The front page to drop a file or type a code, the pickup page, and the transfer handler between them. Everything else is yours to restyle.

- **A drop zone** — Drag a file in or pick one. It lands in your bucket under a fresh code with an expiry stamped on the object, and the page shows the code on a split-flap board, the link to share, and a QR code of that link.
- **Already have a code?** — The other half of the front page: type the eight characters from the other screen, typos repaired as you go (`k7qp-2m4x` reads as `K7QP2M4X`), and land on the pickup page.
- **From a laptop to a phone** — Point the phone’s camera at the QR code next to the board: the pickup page opens on the phone. Download there, and the page offers to burn the code right after, so nothing stays in the bucket.
- **A pickup page** — `/K7QP2M4X` shows the filename, the size and the time left, then hands the bytes over. An unknown or expired code gets the same 404, so nobody can probe which codes were used.
- **One route file** — `createTransferHandler()` serves the four-route protocol, so the CLI works against your deployment too: `s3nd put --remote https://drop.s3nd.sh/api/transfers`.
- **An optional password** — Set `DROP_PASSWORD` and uploading asks for it; picking up never does. Without it, anyone who finds the page can drop a file in your bucket, which is fine behind a proxy and not fine on the open internet.

## Five variables, one lifecycle rule.
The bucket and a key pair scoped to it. Vercel asks for them when you deploy; locally they go in .env.local.

**.env.local**
```sh
S3ND_BUCKET=drop
S3ND_ENDPOINT=https://<account-id>.r2.cloudflarestorage.com
S3ND_REGION=auto
AWS_ACCESS_KEY_ID=…
AWS_SECRET_ACCESS_KEY=…

# optional
DROP_PASSWORD=…              # ask for it before an upload
DROP_EXPIRES_IN=86400        # the default lifetime, in seconds
DROP_MAX_EXPIRES_IN=604800   # the longest a sender may choose
DROP_MAX_SIZE_MB=4           # under Vercel's 4.5 MB request limit
DROP_PREVIEW=true            # show what is behind a code before downloading
```

1. Create a bucket on R2, S3, Scaleway, Wasabi or a MinIO you host, and a key pair with read and write on that bucket and nothing else.
2. Click Deploy, paste the five values, wait for the build.
3. Add a lifecycle rule that deletes objects under the prefix after a day or two: the expiry stops a transfer being handed over, only the rule deletes the object.
4. Run `npx @s3nd/cli doctor --remote https://drop.s3nd.sh/api/transfers` and watch it round-trip a real transfer.

## What it does not do, yet.
- **4.5 MB on Vercel** — A file goes through the function, so Vercel’s request limit applies. `DROP_MAX_SIZE_MB` sets the ceiling below it, and an oversized file is refused before anything is uploaded. Presigned browser uploads, which lift the limit, are on the roadmap.
- **No accounts** — The code is the whole handshake, and it is a bearer token. The default expiry is a day; shorten it with `DROP_EXPIRES_IN` for anything sensitive, or encrypt before dropping.
- **Restyle freely** — Tailwind, two pages, no design system to learn. The split-flap board and the amber are the site’s identity, not the template’s contract.
