SuperAPI AI Directory

tanstack-better-upload

Coding & development

View repository

Updated 10-15 21:42

About this skill

Better Upload (TanStack Start)

@better-upload/server + @better-upload/client — presigned direct-to-S3 uploads via TanStack Start POST handlers and useUploadFiles / useUploadFile.

react-dropzone — optional FMC add-on for drag-and-drop multi-file UX. Add it only when the product needs that interaction (multipleFiles, batch progress). Single-file button/picker flows use Better Upload hooks alone — no dropzone dependency.

Upstream (Better Upload): llms-full.txt · quickstart

When to apply

Better Upload (always relevant for uploads):

  • New upload endpoint under routes/api/
  • useUploadFiles / useUploadFile and upload progress
  • S3 object helpers (getObject, deleteObject, presignGetObject, putObject) via Better Upload — not raw @aws-sdk/client-s3
  • Post-upload DB records via createServerFn + TanStack Query

react-dropzone (only when UX needs it):

  • Drag-and-drop multi-file dropzone with batch progress
  • FMC UploadDropzone* component stack

Single-file pickers, plain <input>, and paste areas call upload() directly — no react-dropzone. Details: dropzone-ui.md.

Architecture (FMC)

Client                          Server API route                 S3
──────                          ────────────────                 ──
file picker / dropzone* onDrop
  → useUploadFiles.upload()  →  handleRequest(router)       →  PUT presigned
  → onUploadComplete         →  onBeforeUpload (auth, keys)
  → create*Fn (server fn)    →  (separate RPC, not Better Upload)
  → invalidate queries

* dropzone = optional react-dropzone layer (multi-file drag-and-drop only)

Two phases: bytes to S3, then app DB row via server function. See troubleshooting.md.

References (read as needed)

Situation File
First-time setup — packages, env, CORS, API route, smoke test first-time-setup.md
Server Router, route(), onBeforeUpload, metadata server-router.md
useUploadFiles, events, DB payload after complete client-hooks.md
Optional multi-file dropzone UI (react-dropzone) dropzone-ui.md
getObject, deleteObject, presignGetObject, S3 client policy s3-helpers.md
Serving uploads (GET proxy, <img> previews, dev Vite plugin) serving-uploads.md
Errors, anti-patterns, debugging troubleshooting.md

Related skills

  • tanstack-router-conventions — routes, search params (when wiring upload UI to URL state)
  • tanstack-start-conventions — layout, .server.ts / .functions.ts, API route boundaries, SSR

Usage rules (daily work)

Topic Rule
Route name Client route: 'upload' must match routes: { upload: route({...}) }
API path Client defaults to /api/upload; set api when the TanStack route differs
Handler return handleRequest(request, router) — no Next.js adapter
Auth Enforce in handler or onBeforeUpload; endpointAuth.inherited(...) when auth lives in handler
DB after upload useMutation({ mutationFn: createUploadFn }) in onUploadComplete
Boundaries Post-upload persistence in *.functions.ts + createServerFn; never import @better-upload/server in client components
S3 access getConfiguredS3Client() (aws()) + @better-upload/server/helpers — not @aws-sdk/client-s3 unless helpers lack the op (s3-helpers.md)
Serve via API GET /api/ routes for <img> / <video> previews need forwardApiRequestsPastViteAssetMiddleware() in vite.config.ts (dev only) — serving-uploads.md

For setup steps and checklists, start with first-time-setup.md.