Demo
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.