Open source
TypeScript-first

A simpler way to handle direct file uploads.

Validate files and prepare secure direct uploads to AWS S3 or ImageKit using one TypeScript SDK.

See the complete upload flow

The browser asks your route handler for a secure upload target, then sends the file directly to your storage provider.

UploadButton.tsx
"use client";
import { useRef, useState } from "react";
export function UploadButton() {  const inputRef = useRef<HTMLInputElement>(null);  const [uploading, setUploading] = useState(false);
  async function uploadFile(file: File) {    setUploading(true);
    try {      const targetResponse = await fetch("/api/upload", {        method: "POST",        headers: {          "Content-Type": "application/json",        },        body: JSON.stringify({          filename: file.name,          contentType: file.type,          size: file.size,        }),      });
      if (!targetResponse.ok) {        throw new Error("Unable to prepare upload");      }
      const preparedUpload = await targetResponse.json();      const formData = new FormData();
      for (const [name, value] of Object.entries(preparedUpload.fields)) {        formData.append(name, value as string);      }
      formData.append("file", file);
      const uploadResponse = await fetch(preparedUpload.url, {        method: preparedUpload.method,        headers: preparedUpload.headers,        body: formData,      });
      if (!uploadResponse.ok) {        throw new Error("Upload failed");      }    } finally {      setUploading(false);    }  }
  return (    <>      <input        ref={inputRef}        type="file"        className="hidden"        accept="image/png,image/jpeg"        onChange={(event) => {          const file = event.target.files?.[0];
          if (file) {            void uploadFile(file);          }        }}      />
      <button        type="button"        disabled={uploading}        onClick={() => inputRef.current?.click()}      >        {uploading ? "Uploading..." : "Choose a file"}      </button>    </>  );}

Supported providers

Use the same upload flow with AWS S3 or ImageKit.