# Next.js boilerplate with Supabase Storage

> Object storage on the Supabase project you already have. A migration creates a private bucket with row level security policies. Signed upload URLs are issued only after an authorisation check. You also get signed downloads, on-the-fly image transformation and a token-only dropzone that uploads straight to storage.

Object storage in your Supabase project, with the same row level security as tables.

- **Category:** Storage
- **Pricing:** Part of your Supabase plan. Free: 1 GB stored and 5 GB egress. Pro: 100 GB stored, then $0.0213/GB, and 250 GB egress, then $0.09/GB ($0.03/GB for cached egress). Image transformations need Pro: 100 origin images included, then $5 per 1,000.
- **Best for:** Teams already on Supabase who want files under the same policies as their rows. Same migrations, same pull request. Strongest for private per-user files (avatars, invoices, imports) where "the owner and nobody else" is the whole access model.
- **Requires:** supabase
- **Vendor docs:** https://supabase.com/docs/guides/storage

## Trade-offs

- Egress is billed. If you serve large media at volume, the transfer line will outgrow the storage line. That is the case R2 exists for.
- Policies are SQL against `storage.objects`, so the key layout is part of your security model. Change the shape of your keys and every policy changes with it.
- The service role key bypasses every policy. Server code that uses it does its own authorisation, and the RLS policies only guard what holds a user token.
- Image transformation is convenient and metered per origin image. Cheap for avatars, surprising for a gallery.
- Signed upload URLs last two hours and that cannot be shortened, so treat the URL itself as a credential.
- One bucket per access model, not per feature. Public and private objects in one bucket end in leaked files or a pile of policy exceptions.

## Known fixes it ships

- [Cleaning up orphaned uploads before they become the bill](https://agenticboilerplate.com/cookbook/supabase-storage/cleaning-up-orphaned-uploads): Every abandoned upload and every deleted row leaves an object nothing references. Here is where orphans come from, the sweeper that finds them, and the two-phase delete that stops making more.
- [Serving images from Supabase Storage without shipping 4 MB avatars](https://agenticboilerplate.com/cookbook/supabase-storage/image-transformation): On-the-fly transformation resizes at read time, but it is metered and it fights your cache. When to transform, when to resize on upload, and how signed URLs complicate both.
- [Public bucket or private bucket: decide once, per bucket, on purpose](https://agenticboilerplate.com/cookbook/supabase-storage/public-vs-private-buckets): A public bucket serves every object to anyone who guesses a key, forever. A private one costs you a signing step and a cache problem. Here is how to choose, and why mixing them in one bucket goes wrong.
- [Row level security on storage buckets, and why yours might not be running](https://agenticboilerplate.com/cookbook/supabase-storage/rls-on-storage-buckets): Storage policies are SQL against storage.objects keyed on the path. Here is the policy set that works, the key layout it depends on, and why the service role key silently bypasses all of it.
- [Signed upload URLs versus proxying the file through your server](https://agenticboilerplate.com/cookbook/supabase-storage/signed-upload-urls-vs-proxying): Proxying uploads through a route handler hits body limits, doubles the transfer and bills you for the wait. Sign a URL instead, and get the order of the checks right.

## Generate it

[Build a repo with Supabase Storage](https://agenticboilerplate.com/build?b=supabase-storage)

---

Agentic Boilerplate: A Next.js repo your agent already knows. $99 once. Lifetime access and updates.

- Site map for agents: https://agenticboilerplate.com/llms.txt
- Public API: https://agenticboilerplate.com/openapi.json
- Contact: agenticstudio@gmail.com
