General
Storage
Manage file uploads and storage with Cloudflare R2 or any S3-compatible provider.
The Pro Next.js Prisma starter kit includes a robust storage service pre-configured for Cloudflare R2, but compatible with any S3 service (AWS S3, DigitalOcean Spaces, etc.).
Configuration
Set up your R2 credentials in the .env file.
.env
S3_ACCESS_KEY_ID="xxxxx"
S3_SECRET_ACCESS_KEY="xxxxx"
S3_ENDPOINT="https://<account-id>.r2.cloudflarestorage.com"
S3_REGION="auto"Storage Functions
The storage functions in lib/storage provide methods for generating signed URLs for both uploads and downloads.
Getting a Signed Upload URL
Generate a short-lived URL on the server that allows the client to upload a file directly to the bucket.
lib/actions/upload.ts
import { storageConfig } from '@/config/storage.config';
import { getSignedUploadUrl } from '@/lib/storage';
const signedUrl = await getSignedUploadUrl(
'avatars/user-1.png',
storageConfig.bucketNames.images
);UI Components
We provide ready-to-use components for common storage tasks.
Avatar Upload
The UserAvatarUpload component handles image selection, cropping and direct upload to R2.
components/user/user-avatar-upload.tsx
import { UserAvatarUpload } from '@/components/user/user-avatar-upload';
export function ProfileSettings() {
return <UserAvatarUpload />;
}Displaying Images
The useStorage hook converts storage paths into accessible URLs automatically.
components/user/user-avatar.tsx
import { useStorage } from '@/hooks/use-storage';
function MyAvatar({ path }) {
const url = useStorage(path);
return (
<img
src={url}
alt="Avatar"
/>
);
}Security
- Signed URLs: All uploads and downloads use time-limited signed URLs.
- Path Validation: All file paths are sanitized to prevent traversal attacks.
- CORS: Ensure your R2/S3 bucket is configured with the correct CORS policy to allow uploads from your domain.