dev.review
Storage · 5 of 5

An S3-compatible bucket

AWS S3, Cloudflare R2, MinIO on a box in the office - anything that speaks the S3 REST API. Plain fetch against it, no SDK, your own credentials.

What it needs

FieldWhat goes there
bucketRequired
regionRequired, e.g. us-east-1
endpointOnly for a non-AWS host - R2, MinIO, a self-hosted gateway
prefixOptional - if drafts do not sit at the bucket's root
access key id / secret access keyRequired, sent as signed headers - never as a query string, never through an SDK's own credential chain

Where it works

Anywhere, given the bucket's own CORS configuration allows the origin this app is running from. Without it, the browser refuses the request before it is even sent, and reports nothing more specific than Failed to fetch - almost always this, not a credential or a typo.

The bucket's CORS rules need to allow this origin for GET, PUT and DELETE, allow the authorization and x-amz-* request headers, and expose etag and x-amz-bucket-region. On AWS, as a bucket CORS policy:

[
  {
    "AllowedOrigins": ["https://app.dev.review"],
    "AllowedMethods": ["GET", "PUT", "DELETE"],
    "AllowedHeaders": ["authorization", "x-amz-*"],
    "ExposeHeaders": ["etag", "x-amz-bucket-region"]
  }
]

Why it exists

No SDK: the four verbs this needs are four verbs, and an SDK would arrive wanting a credential chain that reads files and environment variables that do not exist in a browser. Everything here is a signed fetch against the plain REST API, which is also why any S3-compatible host works rather than only AWS's own.

Every listed object carries the entity tag S3 hands back on write, so two writes of the same length in the same millisecond are still told apart - the one backend among the five that gets this precision for free, rather than falling back to a timestamp.

← A git repository