Type something to search...

Sitepins needs an S3-compatible bucket. Before configuring one, it’s worth being clear about what actually goes in it.

Two Different Kinds of Media

KindExamplesWhere it’s stored
Site content mediaImages in blog posts, anything in your media libraryYour Git repository
Application imagesUser avatars, organization thumbnails, project thumbnailsThe S3 bucket

Your site’s media is committed to Git like everything else — that’s the whole point of a Git-based CMS. The bucket holds Sitepins’ own interface images, which don’t belong in anyone’s repository.

So: if the bucket is misconfigured, avatars and thumbnails break. Your content and its images keep working.

Supported Providers

Anything S3-compatible:

  • AWS S3
  • Cloudflare R2
  • MinIO — self-hosted
  • Backblaze B2
  • DigitalOcean Spaces

Setup

1. Create a bucket

Create a bucket with your provider and generate an access key and secret.

2. Configure the API

In api/.env:

S3_ENDPOINT="https://s3.us-east-1.amazonaws.com"
S3_REGION="us-east-1"
S3_ACCESS_KEY="<access key>"
S3_SECRET_KEY="<secret key>"
S3_BUCKET_NAME="<your bucket name>"
S3_FORCE_PATH_STYLE=false

Provider notes:

  • Cloudflare R2 — set S3_REGION="auto"
  • MinIO and other path-style gateways — set S3_FORCE_PATH_STYLE=true
  • DigitalOcean Spaces — use the Spaces endpoint for your region

3. Configure the app

In app/.env, set the bucket’s public base URL:

NEXT_PUBLIC_BUCKET_URL="https://<bucket>.s3.<region>.amazonaws.com"

This must correspond to the same bucket as the API’s S3_* values, or uploads will succeed and then fail to display.

4. Set CORS on the bucket

Allow your app’s origin in the bucket’s CORS configuration — http://localhost:3000 in development, your real domain in production. Without it, browser uploads are blocked.

Legacy DigitalOcean Variables

Existing DigitalOcean Spaces setups keep working. DOS_PUBLIC_ACCESS_KEY, DOS_PUBLIC_SECRET_KEY, DOS_BUCKET_NAME, and DOS_REGION are still honored and derive the endpoint automatically. New installs should use the S3_* variables.

Verifying It Works

Upload a profile picture at Account → Display Picture. If it uploads and displays, the bucket is configured correctly at both ends.

If it uploads but shows as broken, NEXT_PUBLIC_BUCKET_URL is wrong or the bucket isn’t publicly readable. If the upload itself fails, check the API’s S3_* values and the bucket’s CORS rules.

Content Media Configuration

Your site’s media folders are configured per project, inside the app, not through environment variables. See Configure Your Site and Media Library.