| name | supabase-storage |
| description | Apply when handling file uploads, downloads, and storage management in Supabase. |
| version | 1.0.0 |
| tokens | ~550 |
| confidence | high |
| sources | https://supabase.com/docs/guides/storage, https://supabase.com/docs/reference/javascript/storage-from-upload |
| last_validated | Fri Jan 10 2025 00:00:00 GMT+0000 (Coordinated Universal Time) |
| next_review | Fri Jan 24 2025 00:00:00 GMT+0000 (Coordinated Universal Time) |
| tags | supabase, storage, files, uploads |
When to Use
Apply when handling file uploads, downloads, and storage management in Supabase.
Patterns
Pattern 1: Upload File
// Source: https://supabase.com/docs/reference/javascript/storage-from-upload
async function uploadFile(file: File, userId: string) {
const fileExt = file.name.split('.').pop();
const fileName = `${userId}/${Date.now()}.${fileExt}`;
const { data, error } = await supabase.storage
.from('avatars') // bucket name
.upload(fileName, file, {
cacheControl: '3600',
upsert: false, // false = error if exists, true = overwrite
});
if (error) throw error;
return data.path;
}
Pattern 2: Get Public URL
// Source: https://supabase.com/docs/reference/javascript/storage-from-getpublicurl
// For public buckets
const { data } = supabase.storage
.from('avatars')
.getPublicUrl('user123/avatar.png');
const publicUrl = data.publicUrl;
// With transformations
const { data } = supabase.storage
.from('avatars')
.getPublicUrl('user123/avatar.png', {
transform: { width: 200, height: 200, resize: 'cover' },
});
Pattern 3: Signed URL (Private Buckets)
// Source: https://supabase.com/docs/reference/javascript/storage-from-createsignedurl
const { data, error } = await supabase.storage
.from('private-docs')
.createSignedUrl('user123/document.pdf', 3600); // 1 hour expiry
if (data) {
window.open(data.signedUrl, '_blank');
}
Pattern 4: Delete File
// Source: https://supabase.com/docs/reference/javascript/storage-from-remove
const { error } = await supabase.storage
.from('avatars')
.remove(['user123/old-avatar.png']);
// Delete multiple
const { error } = await supabase.storage
.from('avatars')
.remove(['file1.png', 'file2.png', 'file3.png']);
Pattern 5: React Upload Component
// Source: https://supabase.com/docs/guides/storage
function AvatarUpload({ userId, onUpload }: Props) {
const [uploading, setUploading] = useState(false);
const handleUpload = async (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (!file) return;
setUploading(true);
try {
const path = await uploadFile(file, userId);
onUpload(path);
} catch (error) {
alert('Upload failed');
} finally {
setUploading(false);
}
};
return (
<input
type="file"
accept="image/*"
onChange={handleUpload}
disabled={uploading}
/>
);
}
Anti-Patterns
- No file validation - Check size/type before upload
- Predictable paths - Use UUIDs or timestamps in paths
- No error handling - Handle upload failures gracefully
- Missing RLS on bucket - Configure storage policies
Verification Checklist
- File size limit enforced client-side
- File type validation (accept attribute + server)
- Unique file paths (prevent overwrites)
- Storage policies configured for bucket
- Loading state during upload