File Upload Storage
Configure S3-compatible uploads for NowStack.
NowStack stores uploaded files in S3-compatible Object Storage. Standard deployments commonly use Cloudflare R2; sovereign deployments can use Scaleway Object Storage. 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 with the S3-compatible API, and returns the public URL.
Required Env
Set these values in Convex:
S3_ENDPOINT="https://<account-id>.r2.cloudflarestorage.com"
S3_REGION="auto"
S3_ACCESS_KEY_ID="your-access-key-id"
S3_SECRET_ACCESS_KEY="your-secret-access-key"
S3_BUCKET_NAME="your-bucket-name"
S3_PUBLIC_URL="https://files.yourdomain.com"
S3_KEY_PREFIX=""For local development, you can keep the same values in .env; pnpm start-all syncs missing S3 values into Convex.
Configure Storage
- Create a Cloudflare R2 or Scaleway Object Storage bucket.
- Create S3-compatible access credentials with object read/write access for that bucket.
- Configure a public bucket URL or custom domain.
- Add the
S3_*values to Convex env. - 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
S3_PUBLIC_URL. - The object exists in the configured bucket.
- The image is publicly readable from the returned URL.
If uploads fail with S3 upload environment is not configured, at least one required Convex env value is missing.