# Cloudflare R2 Setup Guide

This guide explains how to configure your application to use Cloudflare R2 for file uploads instead of MinIO.

## What is Cloudflare R2?

Cloudflare R2 is an S3-compatible object storage service with zero egress fees. It works seamlessly with your existing upload infrastructure since you're already using S3-compatible APIs.

## Prerequisites

1. A Cloudflare account with R2 enabled
2. An R2 bucket created
3. R2 API credentials (Access Key ID and Secret Access Key)

## Step 1: Create an R2 Bucket

1. Log in to your [Cloudflare Dashboard](https://dash.cloudflare.com/)
2. Navigate to **R2** in the sidebar
3. Click **"Create bucket"**
4. Choose a bucket name (e.g., `magasinetkbh-uploads`)
5. Select a location (use `auto` for automatic)
6. Click **"Create bucket"**

## Step 2: Get R2 API Credentials

1. In the R2 dashboard, click **"Manage R2 API Tokens"**
2. Click **"Create API token"**
3. Give it a name (e.g., "magasinetkbh-upload")
4. Set permissions:
   - **Object Read & Write** for your bucket
5. Click **"Create API Token"**
6. Save your credentials:
   - **Access Key ID**
   - **Secret Access Key**
   - **Account ID** (you'll need this for the endpoint)

⚠️ **Important**: Save these credentials immediately - you won't be able to see the Secret Access Key again!

## Step 3: Configure Public Access (Optional but Recommended)

For public file access without authentication:

1. Go to your bucket settings
2. Click on **"Settings"** tab
3. Under **"Public access"**, enable **R2.dev subdomain**
4. Note down your public URL (e.g., `https://pub-xxxxx.r2.dev`)

Alternatively, you can configure a custom domain:
1. Click **"Connect domain"**
2. Enter your domain (e.g., `cdn.yourdomain.com`)
3. Follow the DNS configuration steps

## Step 4: Update Environment Variables

Update your `.env.local` file with R2 credentials:

```bash
# Cloudflare R2 Configuration
S3_ENDPOINT=https://<YOUR_ACCOUNT_ID>.r2.cloudflarestorage.com
S3_REGION=auto
S3_ACCESS_KEY_ID=<YOUR_R2_ACCESS_KEY_ID>
S3_SECRET_ACCESS_KEY=<YOUR_R2_SECRET_ACCESS_KEY>
S3_BUCKET_NAME=magasinetkbh-uploads

# Public URL for accessing uploaded files
# Option 1: Use R2.dev subdomain (easiest)
S3_PUBLIC_URL=https://pub-xxxxx.r2.dev

# Option 2: Use custom domain (recommended for production)
# S3_PUBLIC_URL=https://cdn.yourdomain.com
```

### Finding Your Values:

- **Account ID**: Found in your Cloudflare dashboard under R2 section
- **Endpoint**: `https://<ACCOUNT_ID>.r2.cloudflarestorage.com`
- **Region**: Always use `auto` for R2
- **Public URL**: Either your R2.dev subdomain or custom domain

Example configuration:
```bash
S3_ENDPOINT=https://abc123.r2.cloudflarestorage.com
S3_REGION=auto
S3_ACCESS_KEY_ID=1234567890abcdef
S3_SECRET_ACCESS_KEY=abcdef1234567890abcdef1234567890
S3_BUCKET_NAME=magasinetkbh-uploads
S3_PUBLIC_URL=https://pub-xyz789.r2.dev
```

## Step 5: Test the Configuration

1. Restart your development server:
   ```bash
   npm run dev
   ```

2. Try uploading a file through your application

3. Verify the file appears in your R2 bucket dashboard

## Current Code Compatibility

✅ Your existing code is **already compatible** with R2! Here's why:

1. **`forcePathStyle: true`**: Already set in `upload-config.ts` (required for R2)
2. **S3-compatible API**: Your `next-upload` library works with any S3-compatible service
3. **Dynamic configuration**: Your code reads from environment variables

No code changes are needed - just update your environment variables!

## Differences Between MinIO and R2

| Feature | MinIO (Dev) | Cloudflare R2 (Prod) |
|---------|-------------|---------------------|
| Endpoint | `http://localhost:9000` | `https://<account-id>.r2.cloudflarestorage.com` |
| Region | `us-east-1` | `auto` |
| Public Access | Direct endpoint | R2.dev subdomain or custom domain |
| Egress Fees | N/A (local) | $0 (free) |
| Storage Cost | N/A (local) | $0.015/GB/month |

## Production Best Practices

### 1. Use Custom Domain

Instead of R2.dev subdomain, use your own domain for better branding and control:

```bash
S3_PUBLIC_URL=https://cdn.magasinetkbh.dk
```

### 2. Enable CORS (if needed for direct uploads)

In R2 bucket settings, configure CORS:

```json
[
  {
    "AllowedOrigins": ["https://magasinetkbh.dk"],
    "AllowedMethods": ["GET", "PUT", "POST", "DELETE"],
    "AllowedHeaders": ["*"],
    "MaxAgeSeconds": 3000
  }
]
```

### 3. Set Up Lifecycle Rules

Configure automatic deletion of old files if needed:
1. Go to bucket **Settings** → **Lifecycle rules**
2. Add rules for object expiration

### 4. Monitor Usage

Track your R2 usage in the Cloudflare dashboard:
- Storage size
- Class A operations (writes)
- Class B operations (reads)

## Troubleshooting

### Issue: "Access Denied" errors

**Solution**: Verify your API token has the correct permissions for the bucket.

### Issue: Files upload but aren't accessible / Preview images don't display

**Solution**: 
1. **Check if `S3_PUBLIC_URL` is set in Vercel environment variables** - This is the most common issue!
2. Check if public access is enabled on the bucket (R2.dev subdomain must be enabled)
3. Verify `S3_PUBLIC_URL` matches your R2.dev or custom domain exactly
4. Ensure the domain is properly configured in R2 settings
5. Check Vercel logs for errors like "No URL available for uploaded file"

To enable public access on your R2 bucket:
1. Go to Cloudflare Dashboard > R2 > Select your bucket
2. Click **Settings** tab
3. Under **Public R2.dev Bucket URL**, click **Allow Access**
4. Copy the provided URL (e.g., `https://pub-xxxxxxxxxxxxx.r2.dev`)
5. Set this as your `S3_PUBLIC_URL` in Vercel

### Issue: "Invalid endpoint" error

**Solution**: Make sure your endpoint includes your Account ID:
```bash
S3_ENDPOINT=https://<YOUR_ACCOUNT_ID>.r2.cloudflarestorage.com
```

### Issue: CORS errors in browser

**Solution**: Configure CORS settings in your R2 bucket (see Production Best Practices above)

## Migration from MinIO to R2

### Development Workflow

**Option 1: Keep MinIO for development**
```bash
# .env.local (development)
S3_ENDPOINT=http://localhost:9000
S3_REGION=us-east-1
S3_PUBLIC_URL=http://localhost:9000

# .env.production (production)
S3_ENDPOINT=https://abc123.r2.cloudflarestorage.com
S3_REGION=auto
S3_PUBLIC_URL=https://cdn.magasinetkbh.dk
```

**Option 2: Use R2 for both**
Update both development and production to use R2 (with separate buckets).

### Migrating Existing Files

If you have existing files in MinIO that need to be moved to R2:

1. **Using rclone** (recommended):
   ```bash
   # Install rclone
   brew install rclone  # macOS
   
   # Configure MinIO source
   rclone config  # Set up MinIO remote
   
   # Configure R2 destination
   rclone config  # Set up R2 remote
   
   # Sync files
   rclone sync minio:magasinetkbh-uploads r2:magasinetkbh-uploads
   ```

2. **Using AWS CLI with R2**:
   ```bash
   # Configure AWS CLI for R2
   aws configure --profile r2
   
   # Sync from MinIO to R2
   aws s3 sync s3://magasinetkbh-uploads s3://magasinetkbh-uploads \
     --endpoint-url https://<account-id>.r2.cloudflarestorage.com \
     --profile r2
   ```

## Cost Estimation

Cloudflare R2 pricing (as of 2025):
- **Storage**: $0.015 per GB/month
- **Class A operations** (writes): $4.50 per million
- **Class B operations** (reads): $0.36 per million
- **Egress**: **FREE** ✨

Example monthly cost for typical usage:
- 100 GB storage: $1.50
- 100,000 uploads: $0.45
- 1 million downloads: $0.36
- **Total**: ~$2.31/month

## Additional Resources

- [Cloudflare R2 Documentation](https://developers.cloudflare.com/r2/)
- [R2 API Reference](https://developers.cloudflare.com/r2/api/s3/)
- [R2 Pricing](https://developers.cloudflare.com/r2/pricing/)
- [next-upload Documentation](https://next-upload.vercel.app/)

## Support

If you encounter any issues with R2 integration, check:
1. Cloudflare R2 status page
2. Your API token permissions
3. CORS configuration (for direct uploads)
4. Public access settings on the bucket

