BoilerPrompt
Bolt

Bolt prompt to build a file upload endpoint

File uploads in Bolt need a real storage target, since the WebContainer's filesystem resets between sessions, so this prompt sends bytes to a private Supabase bucket and keeps only metadata in the API. Validation is layered and ordered, size first, then magic bytes, giving each rejection a distinct status code you can curl for.

Last updated

Prompt
Build a file upload endpoint in this Bolt project's Express server, storing files in Supabase Storage, because the WebContainer filesystem is wiped between sessions and must never be the system of record.

Route: POST /api/uploads in server/uploads.ts, multipart/form-data with field name file, parsed by multer using memory storage so nothing lingers on disk.

Validation, in this order, each with its own error code:
- 413 file_too_large past 10 MB, enforced through multer limits so oversized bodies abort early.
- 415 unsupported_type unless the magic bytes say png, jpeg, webp, or pdf. Detect with the file-type package, never trusting the client mimetype or the extension.
- 400 missing_file when the field is absent.

Naming and storage: build the object key as uploads/{year}/{month}/{uuid} with the extension taken from the detected type, and keep the original filename only as metadata after stripping path separators and control characters. Upload to a private bucket, then return 201 with id, key, size, contentType, and a short-lived signed URL.

Companion routes: GET /api/uploads/:id returns metadata plus a fresh signed URL, and DELETE removes both the object and the metadata row. Metadata lives in an uploads table with uploader_id taken from the auth middleware.

Failure behavior: if the Storage call dies mid-request, return 502 storage_unavailable and log the attempted key. Insert the metadata row only after the upload succeeds so no half-written records exist.

Acceptance: from Bolt's terminal, curl a small png and get 201, rename an .exe to .png and get 415, send an 11 MB file and get 413, then open the signed URL in the preview and see the image.

Same task in other tools

Questions about this prompt

Why check magic bytes when the request already includes a mimetype?

The client mimetype is whatever the sender claims, and an executable renamed to .png sails through extension checks. Reading the first bytes with file-type verifies what the file actually is. The acceptance script includes exactly that renamed-file case, so you will watch the 415 fire from the terminal.

How do I allow more file types, say mp4 or zip?

Extend the allowlist where the detected type is matched, and revisit the size cap per type, since video at 10 MB is not realistic. For zip specifically, decide whether you will ever unpack server-side, and if so add member-count and decompressed-size guards first, then have Bolt extend the curl checks.

Uploads return 201 but the signed URL gives a 404. Where do I look?

Usually the key returned and the key uploaded differ, often in the extension chosen from the detected type versus the original name, so log both at upload time and compare. The other cause is building a public-bucket URL pattern against a private bucket. Always generate signed URLs through the SDK, never by hand.

Related prompts