MuseMVP Docs

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

ProblemFix
Workers reports missing R2_BUCKETCheck the case-sensitive binding and actual Worker preview/deployment
A Workers link fails outside the app sessionSame-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/.

APIPurpose
GET /api/assetsPaginated files: default 50, maximum 100
GET /api/assets/usageObject count and bytes, aggregating up to 10,000 objects
POST /api/assets/download-urlSession-protected same-origin path
POST /api/assets/deleteUp to 200 keys, with individual results

Keys are scoped to the authenticated user. Preserve ownership validation and list/usage invalidation when extending these flows.

On this page