# @prood/storage-s3 (https://prood.com/docs/packages/storage/s3)

`@prood/storage-s3` implements the `StorageProvider` interface for any S3-compatible object storage — AWS S3, Cloudflare R2, MinIO, or other compatible services.

## Installation [#installation]

Workspace package. Available from the source repo for now.

## Configuration [#configuration]

| Variable | Required | Description |
| --- | --- | --- |
| `S3_ENDPOINT` | Yes | S3-compatible endpoint URL |
| `S3_BUCKET` | Yes | Bucket name |
| `S3_ACCESS_KEY_ID` | Yes | Access key |
| `S3_SECRET_ACCESS_KEY` | Yes | Secret key |
| `S3_PUBLIC_URL` | Yes | Public URL prefix for uploaded files. The apps allow it in `next/image` |

### Cloudflare R2 [#cloudflare-r2]

```bash
S3_ENDPOINT=https://<account>.eu.r2.cloudflarestorage.com
S3_BUCKET=prood-public
S3_ACCESS_KEY_ID=your_access_key
S3_SECRET_ACCESS_KEY=your_secret_key
S3_PUBLIC_URL=https://prood-media.rbarona.workers.dev
```

## Usage [#usage]

Via `@prood/commerce` (preferred):

```ts
import { uploadForTenant } from '@prood/commerce'

const result = await uploadForTenant(orgId, {
  file: buffer,
  filename: 'product-image.jpg',
  contentType: 'image/jpeg',
  directory: `products/${productId}`,
})
```

Direct usage:

```ts
import { S3StorageProvider } from '@prood/storage-s3'

const storage = new S3StorageProvider({
  endpoint: process.env.S3_ENDPOINT!,
  region: 'auto',
  bucket: process.env.S3_BUCKET!,
  accessKeyId: process.env.S3_ACCESS_KEY_ID!,
  secretAccessKey: process.env.S3_SECRET_ACCESS_KEY!,
  publicUrl: process.env.S3_PUBLIC_URL,
})
```

## Tenant namespacing [#tenant-namespacing]

All keys are prefixed with `org/{orgId}/`:

```
org/org_demo/products/prod_abc/image.jpg
```

Always upload via `uploadForTenant()` to ensure proper namespacing.

## Related pages [#related-pages]

<Cards>
  <Card title="Environment variables" href="/docs/run-locally/environment" description="Storage env var reference." />
</Cards>
