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 your first image

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: {
    profile: route({
      fileTypes: ['image/*'],
    }),
  },
};

export const { POST } = toRouteHandler(router);

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

Create <Uploader /> component

We will now build our UI using pre-built components. We'll use <UploadButton /> for single file uploads.

Install it via the shadcn CLI:

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

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

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

import { useUploadFile } from '@better-upload/client';
import { UploadButton } from '@/components/ui/upload-button';

export function Uploader() {
  const { control } = useUploadFile({
    route: 'profile',
  });

  return <UploadButton control={control} accept="image/*" />;
}

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