Workout Window Storage Setup
This document explains how to set up Supabase Storage for the Workout Window feature.
Required Storage Buckets
The Workout Window feature requires one storage bucket:
workout-checkins
This bucket stores user-uploaded check-in photos.
Setup Instructions
1. Create the Storage Bucket
- Go to your Supabase project dashboard
- Navigate to Storage → Buckets
- Click New bucket
- Name:
workout-checkins - Public bucket: ✅ Yes (photos need to be accessible for display)
- File size limit: 10MB (recommended)
- Allowed MIME types:
image/jpeg, image/png, image/gif, image/webp
2. Set Up RLS Policies
The bucket needs Row Level Security (RLS) policies to control access.
Policy 1: Users can upload their own check-ins
CREATE POLICY "Users can upload workout check-in photos"
ON storage.objects
FOR INSERT
TO authenticated
WITH CHECK (
bucket_id = 'workout-checkins' AND
(storage.foldername(name))[1] = auth.uid()::text
);
Policy 2: Users can view their own check-ins
CREATE POLICY "Users can view their own workout check-in photos"
ON storage.objects
FOR SELECT
TO authenticated
USING (
bucket_id = 'workout-checkins' AND
(storage.foldername(name))[1] = auth.uid()::text
);
Policy 3: Users can view other users' check-ins (for chain visibility)
CREATE POLICY "Users can view workout check-in photos in their chain"
ON storage.objects
FOR SELECT
TO authenticated
USING (
bucket_id = 'workout-checkins'
);
Note: Policy 3 makes all check-in photos public to authenticated users. This allows users to see photos from others in their chain. If you want stricter privacy, you can modify this policy to only allow viewing photos from users in the same chain/squad.
Policy 4: Users can delete their own check-ins (optional)
CREATE POLICY "Users can delete their own workout check-in photos"
ON storage.objects
FOR DELETE
TO authenticated
USING (
bucket_id = 'workout-checkins' AND
(storage.foldername(name))[1] = auth.uid()::text
);
3. Storage Structure
Photos are stored with the following structure:
workout-checkins/
{user_id}/
{timestamp}.{extension}
Example:
workout-checkins/
123e4567-e89b-12d3-a456-426614174000/
1704067200000.jpg
1704153600000.png
4. File Naming Convention
- Files are named using a timestamp:
{Date.now()}.{extension} - This ensures unique filenames and prevents conflicts
- The user ID folder structure helps with organization and RLS policies
5. Public URL Access
Since the bucket is public, photos can be accessed via:
https://{project-ref}.supabase.co/storage/v1/object/public/workout-checkins/{user_id}/{filename}
The backend generates these URLs using:
const { data: { publicUrl } } = supabase.storage
.from('workout-checkins')
.getPublicUrl(filePath)
Testing
Test Upload
You can test the upload functionality by:
- Setting up a workout window
- Going to the check-in page
- Uploading a test photo
- Verifying it appears in Supabase Storage
Verify RLS Policies
- Try uploading a photo as User A
- Try accessing that photo as User B (should work if Policy 3 is active)
- Try deleting User A's photo as User B (should fail if Policy 4 is active)
Security Considerations
- File Size Limits: Set a reasonable limit (10MB) to prevent abuse
- MIME Type Validation: Only allow image types
- Content Validation: Consider adding server-side image validation (dimensions, content analysis)
- Rate Limiting: Implement rate limiting on the upload endpoint
- Photo Verification: Consider adding automated or manual photo verification to ensure photos are legitimate
Future Enhancements
- Image Processing: Automatically resize/optimize uploaded images
- Thumbnail Generation: Create thumbnails for faster loading
- EXIF Data Extraction: Extract timestamp and location from photo EXIF data
- Content Moderation: Add automated content moderation for inappropriate photos
Troubleshooting
"Bucket not found" error
- Ensure the bucket name is exactly
workout-checkins - Check that the bucket is created in the correct Supabase project
"Permission denied" error
- Verify RLS policies are set up correctly
- Check that the user is authenticated
- Ensure the file path matches the user's ID
"File too large" error
- Check the bucket's file size limit
- Verify the file is under 10MB
Photos not displaying
- Check that the bucket is set to public
- Verify the public URL is correct
- Check browser console for CORS errors