Storage
Easily set up file storage in your app with Cloudflare R2 or S3-compatible services to handle uploads, downloads, deletions, and public file access.
Tools
- Cloudflare R2 – simple and cost-effective storage (recommended)
- AWS S3 (or any S3-compatible service) – more advanced features
Setup
- Choose a storage provider:
- Cloudflare R2 – recommended for simplicity and low cost
- AWS S3 (or compatible services like MinIO, DigitalOcean Spaces, etc.)
- Create a bucket:
- Go to your provider’s dashboard and create a new bucket (folder for files)
- Copy the credentials: access key, secret key, bucket name, endpoint
- Cloudflare R2 specific steps:
- Sign up / Sign in at Cloudflare
- Create a new R2 bucket:
- Pick a globally unique bucket name (e.g.,
your-project-name) - Select a region close to your target audience
- Pick a globally unique bucket name (e.g.,
- Enable public access: Settings → Public Development URL → Enable
- Save the public URL as
STORAGE_PUBLIC_URL - Optional: Set custom domains for added security
- Save the public URL as
- Create a new API Token:
- Storage & databases > R2 object storage > API Tokens > Manage, click Create User API Token
- Set permissions to Object Read & Write to the bucket
- Copy the Access Key ID and Secret Access Key
- Set the following environment variables:.env
S3_REGION="your-region" # Use "auto" for R2, or e.g. "us-east-1" for S3 S3_BUCKET="your-bucket-name" S3_ACCESS_KEY_ID="your-access-key-id" S3_SECRET_ACCESS_KEY="your-secret-access-key" S3_ENDPOINT="your-s3-endpoint" # Optional S3_PUBLIC_URL="https://cdn.yourdomain.com" # Public URL (CDN or subdomain)
Usage
Storage functions are available in the File Management module in the Admin Panel. Use the useApi composable:
- List files:app/pages/admin/files.vue
const { getStorageFiles } = useApi(); const response = await getStorageFiles(); console.log('File uploaded list:', response.data.blobs); - Upload files:app/pages/admin/files.vue
const { uploadStorageFiles } = useApi(); const selectedFiles = ref<File[]>([]); const response = await uploadStorageFiles(selectedFiles.value); console.log('File uploaded total:', response.data.success); - Download a File:app/pages/admin/files.vue
const { downloadStorageFile } = useApi(); const file = await downloadStorageFile('example.jpg'); - Delete a File:app/pages/admin/files.vue
const { deleteStorageFile } = useApi(); const response = await deleteStorageFile('example.jpg'); console.log('Deleted?', response.success); - Bulk delete files:app/pages/admin/files.vue
const { bulkDeleteStorageFile } = useApi(); const response = await bulkDeleteStorageFile(['example.jpg']); console.log('Deleted Total: ', response.data.success); - Access public file (CDN):app/pages/admin/files.vue
const { public: pub } = useRuntimeConfig(); const imageUrl = `${pub.storagePublicUrl}/example.jpg`; console.log(imageUrl); // https://cdn.yourdomain.com/example.jpg
Best Practices
- File Size Limits: Set reasonable file size limits to prevent abuse
- File Type Validation: Validate file types on both client and server sides for security
Customization
Customize your ShipAhead app with your own logo, favicon, colors, fonts, and Nuxt UI theme. Follow the guide to match your SaaS interface to your brand.
Configure transactional email in your ShipAhead app for verification links and password resets. Learn how to set up the provider and send app emails.