Skip to content
Flows
App Builder Intermediate · 45-90 minutes

File Upload System

Build real file uploads with validation, progress, storage, and display - files must survive refresh.

Start Route · 6 steps

The route

6 steps to Done

  1. 01

    Define upload requirements

    Decide file types, limits, and storage before writing upload code.

    Preview prompt + verify gate ▾

    Define the file upload spec. Specify: allowed file types (e.g. jpg/png/pdf) and max size; where files are stored for this MVP (server uploads directory, database, or object storage) and the tradeoff; the file record model (id, owner, filename, storedPath/url, mimetype, size, uploadedAt); unique storage naming to prevent collisions; and which users can see/delete which files.

    • Allowed types and max size are set
    • Storage location is decided
    • File record fields include owner and unique stored name
  2. 02

    Build the upload UI

    A proper upload surface: picker, drag-drop, validation, and progress.

    Preview prompt + verify gate ▾

    Build the upload UI. Requirements: file picker button plus drag-and-drop zone; client-side validation of type and size with inline error messages before upload; upload progress indicator per file; multiple file selection support; a clear success state per file and a retry option on failure. Do not fake completion - progress must reflect the real request.

    • Wrong type is rejected before upload with a message
    • Oversized file is rejected with the limit shown
    • Progress reflects the actual upload request
  3. 03

    Implement backend storage

    The server must receive, validate, store, and record the file for real.

    Preview prompt + verify gate ▾

    Implement the backend upload endpoint. Requirements: accept multipart uploads; re-validate type and size server-side (reject with 400 and a clear message); store the file with a unique generated name; create the file record with owner id and metadata; return the record including a URL/endpoint to retrieve the file; ensure retrieval actually serves the stored bytes. Uploading two files with the same original name must not collide.

    • Server rejects wrong type/size independently of the client
    • Same-name uploads coexist
    • The returned URL serves the actual file
  4. 04

    List and display uploaded files

    Users must see their files after refresh - the proof uploads are real.

    Preview prompt + verify gate ▾

    Implement the files list. Requirements: fetch the logged-in user's file records from the backend; render image thumbnails for images and type icons for other files; show filename, size, and upload date; clicking opens/downloads the real file; loading skeletons, an empty state for no files, and an error state; the list must be identical after a full page refresh.

    • Files persist across refresh
    • Images render as real thumbnails
    • Another account does not see my files
  5. 05

    Add delete with confirmation

    Deletion must remove both the record and the stored file.

    Preview prompt + verify gate ▾

    Implement file deletion. Requirements: delete button per file with a confirmation dialog; the backend verifies the requester owns the file, deletes the stored bytes and the record; the UI removes the item and shows a success toast; failures show visible errors; a deleted file's URL stops working. Only owners can delete their files.

    • Deleted file is gone after refresh
    • Its URL no longer serves content
    • Another user cannot delete my file
  6. 06

    Upload QA pass

    Verify the full upload lifecycle including hostile inputs.

    Preview prompt + verify gate ▾

    Run upload QA and report PASS/FAIL with evidence: upload valid image and PDF; reject .exe and oversized file (client AND direct-to-server); refresh shows persisted list; two same-name files coexist; delete removes file and kills its URL; second account isolation; mobile layout for the upload zone. Fix all failures and re-run.

    • Server-side rejection tested directly
    • Persistence verified via refresh
    • Ownership isolation verified
    • All failures fixed