Better Upload

Quickstart

You can have file uploads in your React app in a few minutes with Better Upload. This guide will walk you through the steps to set it up with any React framework.

Before you start, make sure you have an S3-compatible bucket ready. You can use AWS S3, Cloudflare R2, or any other S3-compatible service.

Uploading images

Install

Install the @better-upload/server and @better-upload/client packages.

npm i @better-upload/server @better-upload/client

Set up server

Your server generates pre-signed URLs, which the client uses to upload files directly to the S3 bucket.

Change my-bucket to your bucket name, and choose your S3 client.

app/api/upload/route.ts
import { route, type Router } from '@better-upload/server';
import { toRouteHandler } from '@better-upload/server/adapters/next';
import { aws } from '@better-upload/server/clients';

const router: Router = {
  client: aws(), // or cloudflare(), backblaze(), tigris(), ...
  bucketName: 'my-bucket', 
  routes: {
    images: route({
      fileTypes: ['image/*'],
      multipleFiles: true,
      maxFiles: 4,
    }),
  },
};

export const { POST } = toRouteHandler(router);

In the example above, we create the upload route images. Learn more about upload routes here.

Create <Uploader /> component

We will now build our UI using pre-built components. Use <UploadDropzone /> for multiple file uploads.

Install it via the shadcn CLI:

npx shadcn@latest add @better-upload/upload-dropzone

We'll also use the useUploadFiles hook. The complete code looks like this:

uploader.tsx
'use client'; // only for Next.js

import { useUploadFiles } from '@better-upload/client';
import { UploadDropzone } from '@/components/ui/upload-dropzone';

export function Uploader() {
  const { control } = useUploadFiles({
    route: 'images',
  });

  return (
    <UploadDropzone
      control={control}
      accept="image/*"
      description={{
        maxFiles: 4,
        maxFileSize: '5MB',
        fileTypes: 'JPEG, PNG, GIF',
      }}
    />
  );
}

Learn more about the hooks here.

Place the component

Now place the <Uploader /> component in your app.

page.tsx
import { Uploader } from '@/components/uploader';

export default function Page() {
  return (
    <main className="flex min-h-screen flex-col items-center justify-center">
      <Uploader />
    </main>
  );
}

You're done! 🎉

You can now run your app and upload images directly to any S3-compatible service!

If you plan on uploading files larger than 5GB, take a look at multipart uploads.

Learn more

Concepts

Guides

Components