upload-stuff

Comparison

How upload-stuff compares to UploadThing and a hand-rolled presigned-S3 flow.

upload-stuff sits between a managed upload service and rolling your own presigned flow.

Bring your own bucket

UploadThing manages storage for you — no S3 account, no bucket, no CORS. upload-stuff expects your own S3 bucket and credentials: you own your data, your bucket policy, and your bill, and you get an end-to-end typed API over it.

If you never want to touch S3, a managed service is the simpler choice. If you already have (or want) your own bucket, upload-stuff removes the boilerplate without taking over your storage.

The same upload, three ways

avatar: f({ isPublic: true, files: ["image/*"], maxFileSize: "4MB" })
  .middleware(({ ctx }) => ({ userId: ctx.userId }))
  .onUploadComplete(({ middlewareData }) => ({ uploadedBy: middlewareData.userId }))
  .build();

One typed route — middlewareData and the completion payload are fully typed, and the client hook infers its types from this definition (proven, not asserted).

avatar: f({ image: { maxFileSize: "4MB" } })
  .middleware(async ({ req }) => ({ userId: await auth(req) }))
  .onUploadComplete(({ metadata, file }) => {
    console.log(file.url);
  });

file.url points at UploadThing's CDN — managed storage means no bucket to configure, and no bucket you own.

const command = new PutObjectCommand({ Bucket, Key, ContentType });
const url = await getSignedUrl(s3, command, { expiresIn: 3600 });
await fetch(url, { method: "PUT", body: file });

And that is only the presign step — the verification, the database row, the cleanup of abandoned uploads, and the typed client wiring are still yours to write and keep correct.

What you stop owning

  • The presigned-URL handshake and its expiry window.
  • Storage verification when the client claims completion.
  • Pending-row bookkeeping in your database.
  • Finding and deleting abandoned uploads — you schedule cleanUpFiles, it does the sweep.
  • The typed client wiring.

See Type safety for the router-to-client inference end-to-end.

On this page