Skip to content

feat: add pushduck as S3-native upload alternative to UploadThing#68

Open
abhay-ramesh wants to merge 1 commit intoreliverse:mainfrom
abhay-ramesh:feat/add-pushduck-upload-alternative
Open

feat: add pushduck as S3-native upload alternative to UploadThing#68
abhay-ramesh wants to merge 1 commit intoreliverse:mainfrom
abhay-ramesh:feat/add-pushduck-upload-alternative

Conversation

@abhay-ramesh
Copy link
Copy Markdown

Summary

This PR adds pushduck as a parallel, opt-in upload alternative to the existing UploadThing integration. UploadThing is completely unchanged β€” both systems coexist and users can choose either.

What changed

New files:

  • src/app/api/upload/route.ts β€” pushduck API route at /api/upload
  • src/ui/components/pushduck-upload.tsx β€” drop-in <ImageUploader /> and <VideoUploader /> React components

Modified files:

  • .env.example β€” adds AWS_S3_* vars section under UPLOADS
  • package.json β€” adds "pushduck": "^0.4.0" dependency

Why pushduck

UploadThing pushduck
Storage UploadThing-managed CDN Your own S3 / R2 / Spaces / MinIO
Bandwidth cost Included in plan Files go browser β†’ S3 directly (presigned URLs) β€” zero server bandwidth
Vendor lock-in Yes None
Route names imageUploader, videoUploader Same β€” imageUploader, videoUploader

Key design decisions

  • Presigned URL pattern β€” the server only signs the upload; bytes travel directly from the browser to S3. No server bandwidth consumed.
  • Same route slug names as UploadThing (imageUploader, videoUploader) so swapping is a one-line import change.
  • Auth parity β€” middleware uses auth.api.getSession() identically to core.ts, so session handling is consistent.
  • File limits match β€” 4 MB for images, 64 MB for videos, matching the existing UploadThing config.
  • Provider flexibility β€” the AWS_S3_* vars work with any S3-compatible provider (Cloudflare R2, DigitalOcean Spaces, MinIO) by adjusting the endpoint.

Required env vars (optional β€” only if using pushduck)

AWS_S3_ACCESS_KEY_ID=
AWS_S3_SECRET_ACCESS_KEY=
AWS_S3_REGION=us-east-1
AWS_S3_BUCKET_NAME=

Test plan

  • UploadThing still works at /api/uploadthing (nothing changed)
  • <ImageUploader /> from ~/ui/components/pushduck-upload renders and accepts image files
  • <VideoUploader /> from ~/ui/components/pushduck-upload renders and accepts video files
  • Unauthenticated upload attempt returns 401
  • Authenticated upload produces a presigned URL and file lands in the configured S3 bucket
  • Progress bar updates during upload, success URL displayed after completion

πŸ€– Generated with Claude Code

- Add /api/upload route using pushduck/server with imageUploader and videoUploader
- Add ImageUploader and VideoUploader React components using pushduck/client
- Mirror same route names (imageUploader, videoUploader) as UploadThing for easy swap
- Add AWS_S3_* env vars to .env.example (supports R2, Spaces, MinIO too)
- UploadThing integration is untouched β€” pushduck runs in parallel at /api/upload

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant