Skip to main content
Storage is where your app keeps uploaded files and generated media. If you skip this, the basic app still runs, but upload-heavy features like document chat, image generation, and audio won’t work properly.

What Uses Storage

Your app needs storage for:
  • Chat document uploads (PDFs)
  • Generated images
  • Generated videos
  • Generated audio
  • User-uploaded files for vision and other tools

Get It Running

1

Create a bucket

We recommend Cloudflare R2 because it’s S3-compatible and simple to set up. Create a bucket in the R2 dashboard.
2

Generate API credentials

Create an API token with read/write access to your bucket. Copy the S3 endpoint from your R2 dashboard.
3

Configure a public URL

Set up a custom domain or use the default r2.dev URL so your users can access stored files in the browser.
4

Add your env vars

STORAGE_REGION=auto
STORAGE_ACCESS_KEY=your-access-key
STORAGE_SECRET_KEY=your-secret-key
STORAGE_ENDPOINT=https://<account-id>.r2.cloudflarestorage.com
STORAGE_BUCKET=anotherwrapper
STORAGE_PUBLIC_URL=https://cdn.yourdomain.com
5

Restart and test

Restart your dev server, upload a file, and check that the stored file URL opens in the browser.

What Each Env Var Does

VariablePurpose
STORAGE_REGIONRegion value expected by your provider (auto for R2)
STORAGE_ACCESS_KEYAccess key for your bucket
STORAGE_SECRET_KEYSecret key for your bucket
STORAGE_ENDPOINTS3-compatible API endpoint
STORAGE_BUCKETBucket name
STORAGE_PUBLIC_URLThe public URL users will open in the browser
The most important rule: STORAGE_PUBLIC_URL must point to the same bucket your app is uploading into. If your app writes to Bucket A but the public URL points to Bucket B, uploads will succeed but every link will be broken.

Key Files

The main storage logic lives in:
  • lib/storage/object-storage.ts — uploads, deletes, and public URLs
  • lib/integrations/cloudflare.ts — Cloudflare-specific integration

Verify It Works

Your storage setup is working if you can:
  • Upload a file through the app
  • See generated media save successfully
  • Open the stored file URL in your browser
Double-check that STORAGE_BUCKET matches the exact name in your provider dashboard, and that STORAGE_ENDPOINT uses the correct account ID.
Your STORAGE_PUBLIC_URL must resolve to the same bucket you’re uploading to. If you’re using a CDN, make sure it’s configured to serve from the right origin.
Did you restart the app? Next.js doesn’t pick up new env vars until you restart the dev server.