General file storage in your own R2 bucket, with an owner, a quota, and a link you can take back.
@pithy-sh/storage
pithy add storageFiles, with an owner, a quota, and a link you can take back. The plain case: a user uploads something, you decide who may read it, and you can revoke that later.
What it sits on
Uploads never proxy through your Worker: the client PUTs straight to a presigned URL, and anything past 100 MiB becomes resumable parts. Downloads deliberately do stream through it, because that is the only way a read can be authorized per request.
The honest bit
No transcoding, no thumbnails, no AI enrichment. That is media, and keeping them apart is deliberate — most files are just files, and paying for a pipeline you do not need is how storage layers get bloated.
If you build it yourself
Putting bytes in a bucket is one call. Everything around it is the product.
Short-lived, method-limited, and content-type pinned, or you have built an open bucket with extra steps.
Anything past a hundred megabytes needs multipart, part accounting, and a way to resume after a dropped connection.
A signed URL cannot be revoked once shared, which is why downloads stream through the Worker and uploads do not.
Who owns a file, how much they may store, and what happens to their objects when they leave.
Revocation that actually revokes, rather than a URL that keeps working until it expires.
pithy add storageComposes with
In the dashboard
What is stored, who owns it, how much quota is left, and which links are live.
The dashboard is the admin interface for your own application: whatever this capability writes, your team can look up, check and act on from a browser. Reading is free, forever, with no time limit. Connect the project when you deploy.
Everything else
Each one composes the same way. Nothing you skip costs you anything.
Designed, not shipped
Written down, argued out, and not built yet. Each one links to the issue it is being designed in, so you can read the reasoning or disagree with it.
One command installs the package, wires its bindings into every environment your project declares, and runs its migrations.