Storage
Manage file uploads and storage with Cloudflare R2 or any S3-compatible provider.
The Pro Next.js Drizzle starter kit includes a robust storage service pre-configured for Cloudflare R2, but compatible with any S3-compatible service (AWS S3, DigitalOcean Spaces, MinIO, etc.).
Setup
Upload Files
Access Files
Overview
The storage service provides:
- Signed URLs for secure uploads and downloads
- Path validation to prevent security issues
- S3-compatible API supporting multiple providers
- Direct client uploads to reduce server load
Supported Providers
- Cloudflare R2
- AWS S3
- DigitalOcean Spaces
- MinIO
- Any S3-compatible service
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.
import { storageConfig } from '@/config/storage.config';
import { getSignedUploadUrl } from '@/lib/storage';
const signedUrl = await getSignedUploadUrl(
'avatars/user-1.png',
storageConfig.bucketNames.images
);Getting a Signed Download URL
Generate a signed URL for downloading files:
import { storageConfig } from '@/config/storage.config';
import { getSignedUrl } from '@/lib/storage';
const signedUrl = await getSignedUrl(
'avatars/user-1.png',
storageConfig.bucketNames.images,
3600 // Expires in 1 hour (in seconds)
);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.
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.
import { useStorage } from '@/hooks/use-storage';
function MyAvatar({ path }: { path: string }) {
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.
- Access Control: Files are not publicly accessible by default - access is controlled through signed URLs.