Overview
Supabase Storage provides:- Public buckets for user-uploaded media
- Automatic CDN for fast global delivery
- File management with folder organization
- 100MB per file upload limit (configurable)
- Unlimited storage (pay-as-you-go)
Supabase is required for manual sessions and media vault features. Standard (Reddit-based) sessions work without it.
Prerequisites
- Supabase account at supabase.com
- Active project with storage enabled
- Project URL and API keys
Setup Steps
Create Supabase Project
- Sign up at supabase.com
- Click “New Project”
- Choose organization and name
- Select region (choose closest to users)
- Set database password (save this!)
- Click “Create new project”
Project creation takes 1-2 minutes. The dashboard will show “Setting up project…” during initialization.
Get API Credentials
Once your project is ready:
- Navigate to Settings → API
- Find and copy these values:
Project URL
Format:
https://xxxxx.supabase.coFound under “Project URL”Anon Key
Long string starting with
eyJ...Found under “Project API keys” → “anon public”Service Role Key
Long string starting with
eyJ...Found under “Project API keys” → “service_role”Configure Environment Variables
Add credentials to
.env:All three variables are required. The server will throw an error on startup if any are missing.
Initialize Storage Buckets
JOIP automatically creates required buckets on first startup:
- user-media: Personal uploads and manual sessions
- general: Community-shared content
Implementation Details
Bucket Configuration
JOIP creates two public buckets with these settings:- user-media
- general
Purpose: User-specific uploads and manual sessionsSettings:
- Public access: Yes
- Allowed MIME types:
image/*,video/mp4,video/webm - File size limit: Unlimited (enforced in application)
- Folder structure:
users/{userId}/{subfolder}/
- Manual session images:
users/{userId}/manual-sessions/{sessionId}/ - Media vault:
users/{userId}/media-vault/ - Profile pictures:
users/{userId}/profile/
File Upload Flow
File Naming Convention
JOIP generates unique filenames to prevent collisions:Filenames are sanitized to remove special characters and prevent path traversal attacks.
Folder Organization
API Usage Examples
Upload File
Delete File
Delete Folder
List Files
Extract File Path from URL
Error Handling
Storage Error Codes
JOIP returns specific error codes for storage operations:| Code | Description | HTTP Status |
|---|---|---|
STORAGE_CONFIG_ERROR | Missing environment variables | 503 |
STORAGE_UNREACHABLE | Cannot connect to Supabase | 503 |
STORAGE_PREFLIGHT_FAILED | Bucket test upload failed | 503 |
UPLOAD_FAILED | File upload error | 500 |
Common Issues
503: STORAGE_UNREACHABLE
503: STORAGE_UNREACHABLE
Cause: Supabase project is paused or network issueSolution:
- Check project status at app.supabase.com
- Resume paused project (free tier auto-pauses after 7 days inactivity)
- Verify
SUPABASE_URLis correct - Check firewall/network connectivity
- Test with
/api/storage/statusendpoint
413: Payload Too Large
413: Payload Too Large
Cause: File exceeds 100MB limitSolution:
- JOIP enforces 100MB per file in application code
- Compress images before upload
- For videos, consider using external hosting
- Increase limit in
server/upload.tsif needed
401: Unauthorized
401: Unauthorized
404: Bucket Not Found
404: Bucket Not Found
Cause: Buckets not created during initializationSolution:
- Restart server to trigger bucket creation
- Manually create buckets via Supabase dashboard:
- Storage → Create Bucket → “user-media” (public)
- Storage → Create Bucket → “general” (public)
- Check server logs for initialization errors
Storage Management
Monitor Usage
Check storage usage in Supabase dashboard:- Navigate to Storage → Usage
- View total storage consumed
- See breakdown by bucket
- Monitor bandwidth usage
Free tier includes 1GB storage and 2GB bandwidth per month. Upgrade to Pro for 100GB storage.
Automatic Cleanup
JOIP automatically cleans up orphaned files:- Manual sessions: Deletes entire folder when session deleted
- Community content: Preserves files in
generalbucket - User media: Files remain until explicitly deleted by user
Security & Access Control
Supabase buckets use Row Level Security (RLS):- Public Access (Current)
- Private Access (Optional)
Both buckets are configured as public:
- Anyone with URL can view files
- Server-side code controls uploads
- Client validation prevents abuse
This is appropriate for an adult content app where all users are authenticated.
Performance Optimization
CDN & Caching
Supabase Storage includes automatic CDN:- Files served from nearest edge location
- HTTP caching headers set automatically
- No additional configuration needed
Image Optimization
For better performance, optimize images before upload:Batch Operations
For multiple files, upload in parallel:Migration Guide
From Local Storage to Supabase
If migrating from localuploads/ directory:
Troubleshooting
Debug Storage Issues
Test Storage Connectivity
Check Supabase Dashboard
- Navigate to Storage in Supabase dashboard
- Select bucket (e.g.,
user-media) - Browse uploaded files
- Check file sizes and paths
- Download files to verify integrity
Security Best Practices
API Key Protection
- Store keys in
.envonly - Never commit service role key
- Use anon key for client-side (if needed)
- Rotate keys if compromised
Input Validation
- Validate file types (MIME + extension)
- Enforce size limits (100MB default)
- Sanitize filenames (prevent path traversal)
- Check image dimensions if needed
Access Control
- Verify user owns files before operations
- Use userId in paths for isolation
- Implement rate limiting on uploads
- Track upload quotas per user
Content Security
- Scan uploads for malware (optional)
- Validate image integrity
- Block executable file types
- Log all upload/delete operations