Configuration/File Upload Storage

File Upload Storage

Configure Cloudflare R2 uploads for NowStack.

NowStack stores uploaded files in Cloudflare R2. Uploads run through Convex actions, so file storage secrets belong in Convex env rather than in the browser runtime.

How It Works

The active upload implementation lives in convex/files/actions.ts.

It accepts a base64 image payload, validates that the file is an image under the configured size limit, uploads the object to R2 with the S3-compatible API, and returns the public URL.

Required Env

Set these values in Convex:

R2_S3_URL="https://<account-id>.r2.cloudflarestorage.com"
R2_S3_ACCESS_KEY_ID="your-access-key-id"
R2_S3_SECRET_ACCESS_KEY="your-secret-access-key"
R2_S3_BUCKET_NAME="your-bucket-name"
R2_URL="https://files.yourdomain.com"

For local development, you can keep the same values in .env; pnpm start-all syncs missing R2 values into Convex.

Configure R2

  1. Create a Cloudflare R2 bucket.
  2. Create an R2 API token with object read/write access for that bucket.
  3. Configure a public bucket URL or custom domain.
  4. Add the R2_* values to Convex env.
  5. Restart the local dev process so Convex reloads its env.

Verify Uploads

Use a profile or organization image upload flow in the app, then confirm:

  • The returned URL starts with the configured R2_URL.
  • The object exists in the configured R2 bucket.
  • The image is publicly readable from the returned URL.

If uploads fail with R2 upload environment is not configured, at least one required Convex env value is missing.