# Better Upload

By **nic13gamer** · Software & Tools

Better Upload: MIT-licensed React library for direct-to-S3 file uploads with minimal setup, presigned URLs, and drag-and-drop UI components.

- Source: https://better-upload.com
- Repository: https://github.com/Nic13Gamer/better-upload
- Install: `npm i better-upload`
- Tags: react, typescript, open-source, s3, file-upload, nextjs, presigned-url, shadcn
- Pricing: free
- Upvotes: 0

## Features

- Direct browser-to-S3 uploads via server-issued presigned URLs
- useUploadFiles React hook for programmatic upload control
- UploadDropzone drag-and-drop component with accept, max file, and size config
- Server-side Zod validation before any presigned URL is issued
- Split @better-upload/client and @better-upload/server packages for runtime flexibility
- shadcn/ui-compatible copy-paste components
- Works with Next.js, TanStack Start, and any React framework
- MIT-licensed; peer dependency on @aws-sdk/client-s3 keeps SDK version in your control

---

## Why it matters

Most file-upload solutions proxy bytes through your server, which adds latency and, more importantly, doubles your egress bill: data travels server-to-S3 instead of browser-to-S3 directly. Better Upload eliminates that hop by generating presigned URLs server-side and having the browser upload straight to your S3 bucket, so you pay only for what your users actually send to storage.

## The big picture

Better Upload ships two coordinating packages: `@better-upload/client` (the React hook and components) and `@better-upload/server` (the route handler). The client calls your server route, the server validates the request with Zod and issues a presigned URL, then the client uploads the file directly to S3. No file bytes hit your API server.

## How it works

You define an upload route on the server using the Better Upload handler, specifying accepted file types, size limits, and max file counts. The client calls `useUploadFiles({ route: 'images' })` and passes the returned `control` to `UploadDropzone`. Validation via Zod runs before any presigned URL is issued, so bad requests are rejected before storage is touched.

## Zoom in

The split package design carries a non-obvious advantage: because `@better-upload/server` is independent of `@better-upload/client`, you can swap the server handler for a different runtime (such as an Edge function) without touching your client bundle or component tree at all. Per the README, the library reaches into `@aws-sdk/s3-request-presigner` and `@aws-sdk/client-s3` as peer dependencies, keeping your own AWS SDK version in control rather than pinning it inside the library.

## Yes, but

Better Upload is React-only. Non-React frameworks (Vue, Svelte, vanilla JS) are out of scope per the docs. And because uploads bypass your server, server-side post-processing (virus scanning, image transcoding) requires a separate S3 event trigger or a Lambda, not an inline middleware step.

## The bottom line

If you are building a React app that needs file uploads and you already have (or are willing to add) an S3-compatible bucket, Better Upload is the fastest path from zero to a working drag-and-drop uploader with direct storage writes. Start at the [quickstart guide](https://better-upload.com/docs/quickstart) or install via npm: `npm i @better-upload/client @better-upload/server`.

## FAQ

### What is Better Upload?

Better Upload is a MIT-licensed React library that adds direct-to-S3 file uploads to any React-based app with minimal setup. It provides a useUploadFiles hook, an UploadDropzone drag-and-drop component, and a server-side route handler that generates presigned URLs so file bytes never pass through your API server. The project has 1,263 GitHub stars, 67 releases, and its latest server release (v3.0.19) shipped in May 2025.

### How do I install and use Better Upload in my project?

Better Upload is ready to use after running `npm i @better-upload/client @better-upload/server` alongside its peer dependency `@aws-sdk/client-s3`. On the server, you define an upload route with the Better Upload handler; on the client, you call `useUploadFiles({ route: 'your-route' })` and pass the returned `control` to `UploadDropzone`. The library works with Next.js, TanStack Start, and any other React-based framework, per the official quickstart at better-upload.com/docs/quickstart.

### Is Better Upload free? What is the license?

Better Upload is fully free and open-source under the MIT License. There is no hosted service, no usage tier, and no fees of any kind, you bring your own S3-compatible storage bucket and pay only your cloud provider for storage. Per the README, 'You are free to do whatever you want with it.'

### What is Better Upload best suited for?

Better Upload is best for React apps that need drag-and-drop file uploads directly to an S3 bucket, especially when egress cost or upload latency is a concern. Because files travel browser-to-S3 rather than browser-to-server-to-S3, you avoid the double-egress problem of server-proxied patterns. It is also a strong fit for teams using shadcn/ui, since the UI components are designed for copy-paste integration.

### How does Better Upload compare to building presigned-URL uploads myself with the raw AWS SDK?

Better Upload gives you the same direct-to-S3 architecture as a hand-rolled AWS SDK approach, but eliminates all the wiring: Zod validation before presigned URL issuance, a structured server route API, and a drop-in React hook and Dropzone component. Rolling your own with UploadThing or the raw AWS SDK means writing that validation and client-server coordination from scratch; Better Upload collapses it to a few lines of config. The tradeoff is that you stay within Better Upload's React and S3 constraints rather than owning every layer.

### What are Better Upload's main limitations?

Better Upload is React-only, so Vue, Svelte, and vanilla JS frontends are not supported. Because uploads bypass your server, any post-upload processing (virus scanning, image transcoding) must be triggered separately via S3 events or a Lambda rather than as inline middleware. The library also requires you to supply and configure your own S3-compatible bucket; it does not provide managed storage.

---
[View on Analog](https://analoghq.ai/nic13gamer/software-tools/better-upload)