setup-guides

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

  1. Go to your Supabase project dashboard
  2. Navigate to StorageBuckets
  3. Click New bucket
  4. Name: workout-checkins
  5. Public bucket: ✅ Yes (photos need to be accessible for display)
  6. File size limit: 10MB (recommended)
  7. 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:

  1. Setting up a workout window
  2. Going to the check-in page
  3. Uploading a test photo
  4. Verifying it appears in Supabase Storage

Verify RLS Policies

  1. Try uploading a photo as User A
  2. Try accessing that photo as User B (should work if Policy 3 is active)
  3. Try deleting User A's photo as User B (should fail if Policy 4 is active)

Security Considerations

  1. File Size Limits: Set a reasonable limit (10MB) to prevent abuse
  2. MIME Type Validation: Only allow image types
  3. Content Validation: Consider adding server-side image validation (dimensions, content analysis)
  4. Rate Limiting: Implement rate limiting on the upload endpoint
  5. 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
WORKOUT WINDOW STORAGE SETUP — Docs | HiveJournal