S3 SDK replaced with Supabase Storage native SDK in storage.ts

adamwolfe2 drops the AWS S3 client and its request presigner in favor of `@supabase/supabase-js`'s built-in Storage API. The public interface stays the same. The trade-off: fewer dependencies and a simpler env surface, but no more Cloudflare R2 support.

infrastructure

backend/src/lib/storage.ts goes from 104 lines to 39. The four exported functions (uploadFile, downloadFile, deleteFile, getSignedUrl) keep the same signatures, so call sites don't change. What changes is the backend: @aws-sdk/client-s3 and @aws-sdk/s3-request-presigner are gone, and the client is now createClient(url, key, { auth: { persistSession: false } }).storage using the existing Supabase credentials.

The env surface simplifies from five variables (R2_ENDPOINT_URL, R2_ACCESS_KEY_ID, R2_SECRET_ACCESS_KEY, R2_BUCKET_NAME, R2_REGION) down to two (SUPABASE_URL, SUPABASE_SECRET_KEY), both already required for auth. STORAGE_BUCKET takes precedence over the old R2_BUCKET_NAME with a fallback to "mike-documents".

There are two behavior differences to verify before adopting this. First, uploadFile now uses upsert: true, so uploads silently overwrite existing objects rather than failing. If your application uses duplicate-key conflicts as a guard, that behavior is gone. Second, getSignedUrl previously built a ResponseContentDisposition header inline to control the download filename for cross-origin anchors. The new version passes { download: normalizeDownloadFilename(downloadFilename) } to Supabase's createSignedUrl. Test that download filenames render correctly in your target browsers before flipping over in production.

The previous commit (cb87623) had added R2_REGION to keep Cloudflare R2 and Supabase Storage both in play. This commit drops that entirely. If your deployment is on R2, this change is not applicable.

So what Worth importing if you are already on Supabase Storage and want to shed the two `@aws-sdk` packages. The public API is stable, the env simplification is real, and the change is compact enough to review quickly. Check the upsert behavior and signed-URL filename handling before deploying. Skip if you use Cloudflare R2 or any other S3-compatible backend.

View this fork on GitHub →

Spotted something wrong? Or know the PR text has fresher detail than the writeup above?

Commits in this thread

1 commit from adamwolfe2/mike-amcollective, oldest first. Source extracted verbatim from the harvested git log.

SHA Subject Author Date
0c77543c refactor: replace S3 SDK with Supabase Storage JS SDK adamwolfe2 2026-04-30 ↗ GitHub
commit body
Eliminates S3 credentials requirement (dashboard-only, no API).
Uses @supabase/supabase-js (already installed) with SUPABASE_URL +
SUPABASE_SECRET_KEY - both already set as Fly secrets.
All public API (uploadFile, downloadFile, deleteFile, getSignedUrl,
key helpers) is preserved unchanged.

Capture this thread into my fork

Download a single Markdown prompt that tells Claude how to port every commit above into your working tree — adapting paths and structure to match your repo. Run it via claude -p < capture-thread-91.md from inside the repo you want the changes in.

⬇ Download capture-thread-91.md