Storage Setup
NuxtBase supports three storage providers:
locals3r2
For most buyers, the correct first choice is local. It removes infrastructure friction while you validate the product, auth, billing, and admin flows.
Recommended First Choice: Local Storage
Section titled “Recommended First Choice: Local Storage”The default .env.example already uses:
NUXT_STORAGE_PROVIDER=localWhen storage is local, uploaded files are written under:
public/uploads/and public URLs are returned like:
/uploads/{key}This is enough for local development and single-instance staging.
Local Storage on Vercel
Section titled “Local Storage on Vercel”If you deploy NuxtBase to Vercel and keep NUXT_STORAGE_PROVIDER=local, you
should assume uploaded files can disappear.
Why:
- local uploads are written to the function filesystem
- Vercel runtime storage is not durable application storage
- new deployments, new function instances, or scaling events do not guarantee that previously written local files are still available
So the practical rule is:
localis fine for local developmentlocalcan be acceptable for short-lived internal testing if you understand the risklocalis not the right choice for Vercel production if uploaded files must persist
If you want persistent uploads on Vercel, move to object storage such as s3
or r2.
Official Vercel references:
How the Template Uses Storage
Section titled “How the Template Uses Storage”Storage is not just a generic service layer. In the template, uploads also create fileAsset records in the database so the app can track:
- provider
- provider key
- file name
- MIME type
- file size
- public URL
- upload status
That means storage setup affects both file delivery and database-backed product flows.
When to Move Beyond Local
Section titled “When to Move Beyond Local”Use s3 or r2 when you need one or more of these:
- multiple app instances
- persistent shared uploads across deploys
- CDN-backed public asset delivery
- object storage outside the app server filesystem
Switching to S3 or R2
Section titled “Switching to S3 or R2”Set the provider first:
NUXT_STORAGE_PROVIDER=s3or:
NUXT_STORAGE_PROVIDER=r2Then add all required variables:
S3_BUCKET=...S3_REGION=...S3_ENDPOINT=...S3_ACCESS_KEY_ID=...S3_SECRET_ACCESS_KEY=...S3_PUBLIC_URL=https://cdn.example.comAWS S3 Setup
Section titled “AWS S3 Setup”Official AWS references:
Practical setup steps:
- Create an S3 bucket in the AWS region you want to use.
- Create an IAM user or IAM role with the minimum S3 permissions your app needs.
- Generate programmatic credentials for that IAM identity.
- Decide what public base URL your app should return for uploaded files.
- Copy the final values into
.env.
Typical mapping:
NUXT_STORAGE_PROVIDER=s3S3_BUCKET=your-bucket-nameS3_REGION=us-east-1S3_ENDPOINT=https://s3.us-east-1.amazonaws.comS3_ACCESS_KEY_ID=...S3_SECRET_ACCESS_KEY=...S3_PUBLIC_URL=https://your-public-file-domain.example.comFor S3_PUBLIC_URL, use the URL your browser should actually load:
- a CloudFront domain
- a custom CDN domain
- or a direct public bucket URL if that matches your setup
Cloudflare R2 Setup
Section titled “Cloudflare R2 Setup”NuxtBase supports r2 for Cloudflare object storage. In this setup, use
Cloudflare R2 for uploaded files.
Official Cloudflare references:
Practical setup steps:
- Create an R2 bucket in Cloudflare.
- Create an R2 API token and copy the generated Access Key ID and Secret Access Key.
- Copy the bucket’s S3 API endpoint.
- Decide how uploaded files should be publicly served.
- Copy the final values into
.env.
Typical mapping:
NUXT_STORAGE_PROVIDER=r2S3_BUCKET=your-bucket-nameS3_REGION=autoS3_ENDPOINT=https://<account-id>.r2.cloudflarestorage.comS3_ACCESS_KEY_ID=...S3_SECRET_ACCESS_KEY=...S3_PUBLIC_URL=https://assets.example.comFor production, Cloudflare recommends using a custom domain for public
bucket access instead of the r2.dev development URL.
That means:
S3_ENDPOINTshould be the bucket’s S3 API endpoint used by the app to talk to R2S3_PUBLIC_URLshould be the public custom domain that browsers use to load files
Why All S3 Variables Are Required
Section titled “Why All S3 Variables Are Required”The environment validation enforces all six variables whenever the provider is s3 or r2.
That is deliberate:
- the storage client needs bucket, endpoint, and credentials
- public file URLs need
S3_PUBLIC_URL - partial configuration is more dangerous than no configuration
If one of these is missing, startup fails early.
Important Behavior Differences
Section titled “Important Behavior Differences”- files are written to disk
- public URLs come from
/uploads/... - easiest for development
S3 / R2
Section titled “S3 / R2”- files are uploaded through the AWS SDK compatible client
- public URLs are derived from
S3_PUBLIC_URL - deletes attempt to remove the object from the bucket
- presigned upload URLs can be generated
Practical Setup Sequence
Section titled “Practical Setup Sequence”- stay on
localuntil the core app is working - test uploads from the UI
- confirm files appear under
public/uploads/ - only then switch to
s3orr2 - verify that uploaded files resolve through your configured public URL
Common Mistakes
Section titled “Common Mistakes”Using a Private Bucket URL as S3_PUBLIC_URL
Section titled “Using a Private Bucket URL as S3_PUBLIC_URL”S3_PUBLIC_URL should be the URL your browser can actually load, usually a CDN or public bucket base URL.
Forgetting That Local Uploads Live on Disk
Section titled “Forgetting That Local Uploads Live on Disk”If you redeploy or replace the filesystem, local uploads may disappear. That is expected behavior for local storage, not a template bug.
Mixing Provider and URL Assumptions
Section titled “Mixing Provider and URL Assumptions”If NUXT_STORAGE_PROVIDER=local, the app will not use S3_PUBLIC_URL.
If NUXT_STORAGE_PROVIDER=s3 or r2, the app expects object-storage style URLs, not /uploads/....