Drivers
Local disk, S3 and S3-compatible stores (R2, Backblaze, Filebase, Hetzner, MinIO), and Azure Blob behind one API, chosen per disk in config so an app can use several at once.
A local disk in development and S3 in production are the same interface, so the upload path you tested is the upload path that ships. Swapping the driver is a config change, not a rewrite of every call site.
All of it in the same install, with nothing to wire together first.
Local disk, S3 and S3-compatible stores (R2, Backblaze, Filebase, Hetzner, MinIO), and Azure Blob behind one API, chosen per disk in config so an app can use several at once.
Validated multipart handling that hands back a stored path, not a temp file you have to remember to move.
Time-limited URLs for private objects, so a download link can expire without a proxy route in front of it.
Public and private per file, enforced by the driver rather than by whichever route happened to serve it.
Path helpers, mime detection, streaming reads, and directory listings that behave the same on every driver.
On AWS, production buckets sit behind the CloudFront distribution buddy deploy provisions; elsewhere, Cloudflare caches what the server serves.
Buddy scaffolds, runs, and ships this the same way it does the rest of the app.
These share the same models, config, and types, so using them together costs nothing extra.