Turn any upload function into an adapter: your API, Supabase, Firebase, Vercel Blob or anything else.
import { createAdapter } from "@uploadcn/core"An adapter is one async function: it receives the file and returns whatever your backend returns. Report progress and honour the abort signal, and the engine gives you queueing, retries, cancel and the whole UI for free.
"use client"
import { createAdapter } from "@uploadcn/core"
import {
Upload,
UploadDropzone,
UploadDropzoneDescription,
UploadDropzoneTitle,
UploadQueue,
} from "@/components/ui/upload"
/**
* Any upload function becomes an adapter, your API, Supabase, Firebase,
* Vercel Blob or a server action. This one simulates a network call.
*/
const adapter = createAdapter(async ({ file, signal, onProgress }) => {
for (let loaded = 0; loaded < file.size; loaded += file.size / 20) {
signal.throwIfAborted()
await new Promise((resolve) => setTimeout(resolve, 60))
onProgress(loaded)
}
return { url: `https://cdn.example.com/${encodeURIComponent(file.name)}` }
})
export default function CustomAdapterExample() {
return (
<Upload adapter={adapter} className="max-w-md">
<UploadDropzone size="sm">
<UploadDropzoneTitle>Your own upload function</UploadDropzoneTitle>
<UploadDropzoneDescription>
Progress, cancel and retry still work
</UploadDropzoneDescription>
</UploadDropzone>
<UploadQueue size="sm" />
</Upload>
)
}
const adapter = createAdapter(async ({ file, signal, onProgress, item }) => {
// item.meta has anything you attached, e.g. the slot name
const result = await uploadSomewhere(file, { signal, onProgress })
return result // becomes item.result
})Prop
Type
Throw an UploadError to control retries: retryable: true for transient failures,
false for permanent ones. Plain errors and HTTP 5xx/429 are retried; 4xx are not.
Recipes
No wrapper needed: httpAdapter posts multipart/form-data with progress:
import { httpAdapter } from "@uploadcn/core"
const adapter = httpAdapter({
url: "/api/files",
headers: async () => ({ authorization: `Bearer ${await getToken()}` }),
})S3-compatible services
MinIO, DigitalOcean Spaces, Backblaze B2, Wasabi and Google Cloud Storage (interop)
speak the S3 API. Use s3Storage with their endpoint on the server and s3Adapter
in the browser:
s3Storage({
bucket: "uploads",
region: "us-east-1",
endpoint: "https://minio.example.com",
accessKeyId: process.env.S3_ACCESS_KEY_ID!,
secretAccessKey: process.env.S3_SECRET_ACCESS_KEY!,
})