Getting Started

From zero to a production upload UI in a few lines.

1. A complete uploader

The fastest path is a block. It's a regular component in your project:

import { FileUpload } from "@/components/file-upload"

<FileUpload accept="image/*,application/pdf" maxSize={20_000_000} maxFiles={10} />

Files are validated in the browser, queued (three at a time), uploaded directly to your bucket through /api/upload, retried on network errors, and shown with progress, speed and time remaining.

2. Compose your own

Blocks are built from the upload primitives. Use them to shape your own layout:

import { s3Adapter } from "@uploadcn/core"

import {
  Upload,
  UploadDropzone,
  UploadDropzoneTitle,
  UploadQueue,
} from "@/components/ui/upload"

const adapter = s3Adapter({ endpoint: "/api/upload" })

export function Attachments() {
  return (
    <Upload adapter={adapter} accept={["image/png", "image/jpeg"]} maxSize={10 * 1024 * 1024} maxFiles={5}>
      <UploadDropzone>
        <UploadDropzoneTitle>Drop images here</UploadDropzoneTitle>
      </UploadDropzone>
      <UploadQueue />
    </Upload>
  )
}

UploadQueue is itself a composition of UploadList, UploadItem, UploadPreview, UploadName, UploadProgress, UploadStatus and the action buttons, see Upload for every part.

3. Control it from outside

Create the engine with useUploader (or useUpload, which also returns state) when other parts of the page need to react to uploads:

import { s3Adapter } from "@uploadcn/core"
import { useUpload } from "@uploadcn/react"

const adapter = s3Adapter({ endpoint: "/api/upload" })

export function Composer() {
  const { uploader, summary } = useUpload({
    adapter,
    onSuccess: (item) => console.log("stored at", item.result?.key),
  })

  return (
    <>
      <Upload uploader={uploader}>
        <UploadDropzone />
        <UploadQueue />
      </Upload>
      <Button disabled={summary.isUploading}>Publish</Button>
    </>
  )
}

4. Pick a storage adapter

You have…Use
S3, R2, MinIO, B2, Spacess3Adapter + @uploadcn/server
A signed-URL API (GCS, Supabase…)presignedAdapter
An endpoint that accepts fileshttpAdapter
A tus servertusAdapter
Your own chunk protocolmultipartAdapter
No backend yetmockAdapter

Next steps

On this page