$npx -y skills add komunite/tezgah --skill saas-storageSaaS uygulaması için Supabase Storage ile dosya depolama altyapısı kur. Bucket yapılandırması, RLS ile dosya güvenliği, dosya yükleme, görsel optimizasyonu ve plan bazlı depolama limitleri. Bu skill'i kullanıcı dosya yükleme, görsel, depolama, storage, upload veya profil fotoğraf
| 1 | # SaaS Storage — Supabase Storage ile Dosya Depolama |
| 2 | |
| 3 | Bu skill, bir SaaS uygulamasının dosya depolama katmanını Supabase Storage ile kurar. Profil fotoğrafları, kullanıcı tarafından yüklenen dokümanlar, ürün görselleri veya dışa aktarılan raporlar — dosya depolama çoğu SaaS'ta gerekli bir katmandır. |
| 4 | |
| 5 | Supabase Storage, zaten veritabanı için kullandığın Supabase projesinin parçasıdır — ek servis hesabı veya yapılandırma gerektirmez. RLS ile dosya seviyesinde güvenlik, dahili görsel dönüştürme ve Dashboard'da görsel dosya yönetimi sunar. Ücretsiz katman: 1 GB depolama, 2 GB bandwidth/ay. |
| 6 | |
| 7 | **Bağımlılık:** Bu skill **saas-launcher** orkestratör skill'inin opsiyonel bir fazıdır. Bağımsız olarak da kullanılabilir. Her SaaS'ta gerekmez — yalnızca dosya yükleme ihtiyacı varsa uygula. |
| 8 | |
| 9 | **Bağlı skill'ler:** |
| 10 | - **saas-database** — Dosya metadata'sı (isim, boyut, tür, URL) veritabanında saklanır. Supabase Storage aynı projenin parçasıdır. |
| 11 | - **saas-auth** — Dosya erişimi kullanıcı kimliğine bağlıdır. |
| 12 | - **saas-api-security** — Yükleme endpoint'leri input validation ve rate limiting gerektirir. |
| 13 | |
| 14 | --- |
| 15 | |
| 16 | ## Supabase Storage Kurulumu |
| 17 | |
| 18 | ### Bucket Oluşturma |
| 19 | |
| 20 | Supabase Storage'da dosyalar bucket'larda organize edilir. Her bucket bir klasör gibidir. |
| 21 | |
| 22 | Önerilen bucket yapısı: |
| 23 | - `avatars` — Kullanıcı profil fotoğrafları (public) |
| 24 | - `uploads` — Kullanıcı dosyaları (private — RLS ile korunmalı) |
| 25 | - `exports` — Sistem tarafından üretilen dosyalar (private) |
| 26 | |
| 27 | **Public vs. Private bucket:** |
| 28 | - Public: Dosya URL'si ile herkes erişebilir. Profil fotoğrafları, ürün görselleri için. |
| 29 | - Private: Erişim RLS politikalarına tabidir. Kullanıcı dokümanları, hassas dosyalar için. |
| 30 | |
| 31 | ### RLS Politikaları |
| 32 | |
| 33 | Storage bucket'ları da veritabanı tabloları gibi RLS ile korunur: |
| 34 | |
| 35 | - **Profil fotoğrafı yükleme:** Kullanıcı sadece kendi klasörüne (`avatars/{user_id}/`) yükleyebilsin |
| 36 | - **Dosya okuma:** Kullanıcı sadece kendi dosyalarını görebilsin |
| 37 | - **Dosya silme:** Kullanıcı sadece kendi dosyalarını silebilsin |
| 38 | |
| 39 | Klasör yapısı ile RLS'i birleştir: `{bucket}/{user_id}/{dosya}` — bu sayede `auth.uid()` ile yol kontrolü yapılabilir. |
| 40 | |
| 41 | --- |
| 42 | |
| 43 | ## Dosya Yükleme Mimarisi |
| 44 | |
| 45 | ### Client-Side Yükleme (Küçük Dosyalar) |
| 46 | |
| 47 | Supabase Storage client'ı ile doğrudan tarayıcıdan yükleme: |
| 48 | 1. Kullanıcı dosya seçer |
| 49 | 2. Client-side validation (tür, boyut) |
| 50 | 3. Supabase Storage API'ye doğrudan yükleme |
| 51 | 4. URL'yi veritabanına kaydet |
| 52 | |
| 53 | **Avantaj:** Basit, sunucu yükü yok. |
| 54 | **Limit:** Maksimum dosya boyutu Supabase client'ta varsayılan 5 MB (yapılandırılabilir). |
| 55 | |
| 56 | ### Presigned URL ile Yükleme (Büyük Dosyalar) |
| 57 | |
| 58 | Büyük dosyalar için sunucu üzerinden presigned URL oluştur: |
| 59 | 1. Client → sunucuya yükleme isteği gönder (dosya adı, tür, boyut) |
| 60 | 2. Sunucu validation yapar, presigned upload URL oluşturur |
| 61 | 3. Client → presigned URL'ye doğrudan yükleme yapar |
| 62 | 4. Sunucu → yükleme tamamlandığını doğrular, metadata'yı veritabanına kaydeder |
| 63 | |
| 64 | **Avantaj:** Sunucu dosya içeriğini taşımaz, bandwidth tasarrufu. Büyük dosyalar desteklenir. |
| 65 | |
| 66 | --- |
| 67 | |
| 68 | ## Dosya Güvenliği |
| 69 | |
| 70 | ### Input Validation |
| 71 | |
| 72 | Dosya yüklemede şu kontrolleri yap: |
| 73 | |
| 74 | 1. **Dosya türü kontrolü:** İzin verilen MIME türlerini belirle. Yalnızca beklenen türleri kabul et. |
| 75 | - Profil fotoğrafı: `image/jpeg`, `image/png`, `image/webp` |
| 76 | - Doküman: `application/pdf`, `text/plain` |
| 77 | - **Yapma:** `*/*` veya tüm türlere izin verme |
| 78 | |
| 79 | 2. **Dosya boyutu kontrolü:** Maksimum boyut belirle. |
| 80 | - Profil fotoğrafı: 5 MB |
| 81 | - Doküman: 10-50 MB |
| 82 | - **Yapma:** Sınırsız yüklemeye izin verme — depolama maliyeti ve DDoS riski |
| 83 | |
| 84 | 3. **Dosya adı temizleme:** Kullanıcının gönderdiği dosya adını güvenme. UUID ile yeniden adlandır. Orijinal adı metadata olarak sakla. |
| 85 | |
| 86 | 4. **Magic bytes kontrolü (ileri seviye):** MIME türü header'ı manipüle edilebilir. Dosyanın ilk byte'larını (magic bytes) kontrol ederek gerçek türünü doğrula. |
| 87 | |
| 88 | ### Rate Limiting |
| 89 | |
| 90 | Yükleme endpoint'ine rate limit uygula: |
| 91 | - Kullanıcı başına dakikada 10 yükleme |
| 92 | - Kullanıcı başına günlük toplam boyut limiti (plan bazlı) |
| 93 | |
| 94 | ### Zararlı İçerik |
| 95 | |
| 96 | - Yüklenen görselleri process et (resize/compress) — bu işlem gömülü zararlı kodları temizler |
| 97 | - Dokümanları kullanıcıya sunarken `Content-Disposition: attachment` header'ı ile indirmeye zorla, tarayıcıda açmaya değil |
| 98 | - Mümkünse ayrı bir domain'den servis et (XSS izolasyonu) |
| 99 | |
| 100 | --- |
| 101 | |
| 102 | ## Görsel Optimizasyonu |
| 103 | |
| 104 | ### Neden Önemli |
| 105 | |
| 106 | Optimize edilmemiş görseller sayfa yükleme süresini katlar. 5 MB'lık bir profil fotoğrafı yerine 50 KB'lık optimizeli versiyon kullanıcı deneyimini dramatik iyileştirir. |
| 107 | |
| 108 | ### Supabase Image Transformation |
| 109 | |
| 110 | Supabase Storage dahili görsel dönüştü |