Documentation menu

Client Mode vs Server Mode

@upupjs/react supports local-only collection plus two upload hosts. mode controls where upload/provider operations run, not whether users can select local files.

Client modeBrowserdirect uploadS3-compatiblestorageServer modeBrowsersigned requestYour server@upupjs/serverpresigned PUTS3-compatiblestorage
tsx
<UpupUploader />                                 // local file collection only
<UpupUploader uploadEndpoint="/api/upload-token" /> // client-hosted upload flow
<UpupUploader mode="server" serverUrl="/api/upup" />

Client mode

Browser talks directly to storage. Your server's only job is to sign short-lived upload URLs.

browser ──POST /sign──> your server
browser <──presigned URL─ your server
browser ──PUT bytes────> S3 / R2 / etc.

Cloud drives (Google Drive, OneDrive, Dropbox, Box) use OAuth from the browser — tokens stay in browser memory, never touch your server.

Choose client mode when:

  • You want the simplest setup.
  • You're OK exposing OAuth client IDs (not secrets) to the browser.
  • You don't need server-side virus scanning or compliance logging inside the upload path.
  • Latency matters — bytes go direct to storage, no relay hop.

Server mode

Browser talks only to your server. Your server proxies drive APIs, stores OAuth tokens, and writes bytes to storage.

browser ──GET  /files/:provider ──> your server ──> Google / MS / ...
browser ──POST /files/:provider/transfer ──> your server ──> S3

The uploader hits one origin. You own the access tokens and the storage credentials.

Choose server mode when:

  • Compliance or policy forbids shipping OAuth client secrets or storage credentials to the browser.
  • You want to scan, log, or transform files on the server before they reach storage.
  • Your end users can't reach the drive APIs directly (corporate firewall, region block).
  • Files may be larger than the browser can hold in memory. Server mode streams drive → S3 without buffering the whole file.

What changes between modes?

ConcernClient modeServer mode
Upload targetuploadEndpointserverUrl
OAuth client IDShipped to browserServer-only
OAuth client secretNot usedServer-only, required
Drive API callsBrowser → providerServer → provider
Storage credentialsSigned URLs onlyServer holds real creds
MultipartBrowser-coordinatedServer-coordinated
Re-auth on token expirySame: user re-signs-inSame: user re-signs-in

Feature parity

Every UpupUploader event callback (onFilesSelected, onUploadStart, onFileUploadComplete, etc.) fires identically in both modes. Theme slots, i18n, file limits (maxFiles, maxFileSize, allowedFileTypes), image editor — all work the same.

The differences are strictly on the wire, not on the API surface.

Migration

If neither uploadEndpoint nor serverUrl is configured, the uploader stays in local file collection mode and calling upload() returns a typed no-target error.