BoilerPrompt
v0

v0 prompt to build a file upload endpoint

Uploads on Vercel hit function body limits fast, so this prompt uses the Blob client upload pattern where files skip the server entirely and a token controls type, size, and pathname. v0 generates the handleUpload route, a progress-tracking drop zone, and the database bookkeeping that makes listing and deletion reliable.

Last updated

Prompt
Build a file upload endpoint on Vercel Blob using the client upload pattern, so files travel from the browser straight to Blob storage and never through a serverless function body limit. Server: app/api/upload/route.ts uses handleUpload to issue client tokens, restricting allowed content types to png, jpeg, and pdf, setting a maximum size in the token so oversized files are rejected before transfer, and prefixing pathnames with the authenticated user id so one user cannot overwrite another's files. The onUploadCompleted callback writes a row to an uploads table in {{database}} with url, pathname, size, and content_type, and that table is the source of truth for listing, never Blob list calls at request time. Client: a drop zone component with drag state styling, a per-file progress bar driven by the upload helper's progress events, an image preview from an object URL before the upload finishes, and a cancel control mid-flight. Rejections happen client side first, wrong type or too large shows an inline message naming the limit without a network round trip, and the server enforces the same rules regardless. Edge cases: duplicate filenames get random suffixes from the Blob helper rather than overwriting, a network drop mid-upload leaves a retry action on the failed item, and deleting an upload removes the Blob first and the database row second, tolerating a Blob that is already gone. A missing BLOB_READ_WRITE_TOKEN shows a setup notice in the v0 preview rather than a crash. Acceptance: upload a png, see its row in the list, delete it, and confirm its URL then returns not found.

Customize it

Runs in your browser. Nothing you type here is sent anywhere.

Your customized prompt
Build a file upload endpoint on Vercel Blob using the client upload pattern, so files travel from the browser straight to Blob storage and never through a serverless function body limit. Server: app/api/upload/route.ts uses handleUpload to issue client tokens, restricting allowed content types to png, jpeg, and pdf, setting a maximum size in the token so oversized files are rejected before transfer, and prefixing pathnames with the authenticated user id so one user cannot overwrite another's files. The onUploadCompleted callback writes a row to an uploads table in PostgreSQL with url, pathname, size, and content_type, and that table is the source of truth for listing, never Blob list calls at request time. Client: a drop zone component with drag state styling, a per-file progress bar driven by the upload helper's progress events, an image preview from an object URL before the upload finishes, and a cancel control mid-flight. Rejections happen client side first, wrong type or too large shows an inline message naming the limit without a network round trip, and the server enforces the same rules regardless. Edge cases: duplicate filenames get random suffixes from the Blob helper rather than overwriting, a network drop mid-upload leaves a retry action on the failed item, and deleting an upload removes the Blob first and the database row second, tolerating a Blob that is already gone. A missing BLOB_READ_WRITE_TOKEN shows a setup notice in the v0 preview rather than a crash. Acceptance: upload a png, see its row in the list, delete it, and confirm its URL then returns not found.

Same task in other tools

Questions about this prompt

Why client uploads instead of posting the file to my own route handler?

Serverless request bodies have hard size ceilings, so routing file bytes through your function fails on exactly the files users care about. The token pattern keeps the server in control of type, size, and pathname while the bytes go directly to Blob storage.

How do I restrict uploads to signed-in users?

The token issuance in handleUpload runs on your server, so check the session there and throw for anonymous requests. No token means no upload, and the same spot is where the user id prefix gets added to the pathname.

onUploadCompleted never fires while I test. Where did the row go?

That callback is a webhook delivered to a reachable URL, so it depends on where the app is running. If rows are missing, have the client record the upload through a server action after the helper reports success, and let the callback reconcile by pathname when it arrives.

Related prompts