Object Storage
Connect object storage, upload an avatar, and check your asset list.
Configure storage for avatar uploads and the account asset manager. Web Cloudflare uses native R2 through the R2_BUCKET binding; S3 credentials are not needed.
Before You Start
Have a running app and a test user. Create a development R2 bucket. Keep development and production resources separate and credentials on the server.
1. Connect Storage
Native R2
Create an R2 bucket and set the binding in apps/web-cloudflare/wrangler.jsonc:
{
"r2_buckets": [
{ "binding": "R2_BUCKET", "bucket_name": "your-bucket-name" }
]
}Merge this into the existing file. Keep the binding name R2_BUCKET; replace the bucket name. Run pnpm cf:typegen after binding changes. Avatar upload/read uses the app's session-protected /files/avatars/* path, so you do not need a public R2 domain or S3 credentials. Test the built Worker with pnpm cf:preview; see Cloudflare Deployment.
2. Upload Your First Avatar
Restart the local app after configuration. Sign in, open /app/settings/general, select an image and complete the avatar crop/upload. Then open /app/settings/storage to inspect the file list and usage, download your own file, and delete a test asset you no longer need.
The Workers avatar route accepts the app's PNG avatar naming format and a nonempty payload up to 5 MiB. For arbitrary file uploads, add a dedicated upload flow with its own validation and permissions.
Check Your Result
- The uploaded avatar appears in your profile and after refresh.
- Your file is listed on the Storage settings page and can be downloaded.
- Deleting a test asset refreshes the list and usage.
- Another user cannot download or delete your session-protected assets.
Common Problems
| Problem | Fix |
|---|---|
Workers reports missing R2_BUCKET | Check the case-sensitive binding and actual Worker preview/deployment |
| A Workers link fails outside the app session | Same-origin asset access requires login and ownership; it is not a public sharing link |
Reference for Custom Uploads
src/server/storage.ts selects the app's driver. Asset APIs live in src/backend/api/routes/assets/, with UI under src/modules/settings/components/assets/.
| API | Purpose |
|---|---|
GET /api/assets | Paginated files: default 50, maximum 100 |
GET /api/assets/usage | Object count and bytes, aggregating up to 10,000 objects |
POST /api/assets/download-url | Session-protected same-origin path |
POST /api/assets/delete | Up to 200 keys, with individual results |
Keys are scoped to the authenticated user. Preserve ownership validation and list/usage invalidation when extending these flows.