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 uses S3-compatible storage and presigned URLs.

Before You Start

Have a running app and a test user. Prepare a bucket, API endpoint, scoped access credentials, and a public read URL for avatar previews. Keep development and production resources separate and credentials on the server.

1. Connect Storage

S3-Compatible Bucket

Create a bucket with your chosen S3-compatible provider. Obtain its endpoint and scoped credentials, then fill apps/web/.env.local:

S3_ENDPOINT="https://YOUR_S3_ENDPOINT"
S3_ACCESS_KEY_ID="YOUR_ACCESS_KEY"
S3_SECRET_ACCESS_KEY="YOUR_SECRET_KEY"
S3_REGION="auto"
S3_AVATARS_BUCKET="avatars"
S3_AVATARS_PROXY_URL="https://YOUR_PUBLIC_READ_BASE"

Use the actual region required by your provider. S3_AVATARS_BUCKET must name your existing bucket; avatars is only the default. The read base is the URL prefix from which a relative object key can be read, not necessarily the S3 API endpoint.

The browser uploads directly using a signed URL. Configure bucket CORS to allow your development origin (http://localhost:3000) and production origin with the operations your upload flow uses. Configure public read access or your read proxy separately if using a public preview prefix.

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.

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
503 STORAGE_ENV_MISSING on NodeCheck all required S3 credentials and restart
Signed upload is blocked by the browserCheck bucket CORS and the exact local/production origin
Upload succeeds but preview is brokenCheck the read prefix and object read permissions; an API endpoint is not always a public read URL

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-urlSigned download URL (900 seconds)
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