Supabase Storage upload, drag and drop
The free upload dropzone with Supabase Storage as its uploader. Errors land on the file's row with a retry button. MIT.
Use it in Next.js
"use client";
import UploadDropzone, { type Uploader } from "@/components/upload-dropzone/UploadDropzone";
import { createClient } from "@/lib/supabase/client";
const supabase = createClient();
const upload: Uploader = async (file, onProgress) => {
const path = `${crypto.randomUUID()}-${file.name}`;
const { error } = await supabase.storage.from("uploads").upload(path, file);
if (error) throw new Error(error.message); // shows on the file row, with a retry button
onProgress(100);
};
export default function UploadPage() {
return <UploadDropzone upload={upload} accept="image/*,.pdf" maxSize={10 * 1024 * 1024} />;
}import { createBrowserClient } from "@supabase/ssr";
export function createClient() {
return createBrowserClient(process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!);
}Good to know
- supabase-js upload doesn't report progress, so the bar goes from 0 to 100 when the file finishes. For a real bar on big files, use Supabase's resumable (TUS) uploads inside the same upload function.
- Throw an Error inside upload and the dropzone shows its message on that file with a retry button.
- The bucket ('uploads' here) needs a storage policy that lets the signed-in user insert, or Supabase answers with a row-level security error.
- maxSize and accept are checked in the browser only. Set the same limits on the bucket.
Install
- One command
npx shadcn@latest add https://teodoravadani.github.io/qodesign-free/r/upload-dropzone.json - Or ask your AIPaste PROMPT.md into Cursor, Lovable or v0.
Props
- upload
- (file, onProgress, signal) → Promise
- maxSize
- bytes, 50 MB by default
- accept
- for the file picker, e.g. image/*
- onAllDone
- every file finished
How qodesign compares
- qodesign vs 21st.dev21st.dev is best for: browsing a huge marketplace and copying many components a month.
- qodesign vs Magic UIMagic UI is best for: landing pages built with shadcn/ui.
All comparisons, with prices read on each library's own site.
Questions
Is it free?
Yes. MIT licence, installed from the free registry.
Can I upload to S3 or UploadThing instead?
Yes. Only the upload function changes.
Can Cursor or v0 add it for me?
Yes. The folder has a PROMPT.md. Paste it into Cursor, Lovable, v0 or Claude Code.
Does the dropzone work in Next.js?
Yes, as a client component. Keep "use client" at the top of the file that renders it, as in the snippet above. App Router and Pages Router both work.