Bölüm 11 — Konu 51: Supabase Alternatifi
Dizi · 51/61 Flutter Türkçe Tutorial
- Bölüm 1 — Konu 1: Flutter Nedir, Mimarisi (Widget → Element → RenderObject, Skia/Impeller)
- Bölüm 1 — Konu 2: Ortam Kurulumu (Flutter SDK, Android Studio/VS Code, Emulator/Simulator, DevTools'a İlk Bakış)
- Bölüm 1 — Konu 3: İlk Proje Yapısı (`pubspec.yaml`, `lib/`, Klasör Mimarisi, `flutter create` Anatomisi)
- Bölüm 1 — Konu 4: Hot Reload / Hot Restart Ne Yapıyor, Neden Önemli
- Bölüm 2 — Konu 5: "Her Şey Widget'tır" Felsefesi, Widget Ağacı
- Bölüm 2 — Konu 6: StatelessWidget vs StatefulWidget + `setState()` Derinlemesine (Rebuild Mekanizması)
- Bölüm 2 — Konu 7: Temel Layout — Container, Row, Column, Stack, Padding, Align, Center
- Bölüm 2 — Konu 8: Constraint Sistemi — "Constraints Go Down, Sizes Go Up, Parent Sets Position"
- Bölüm 2 — Konu 9: `Expanded`, `Flexible`, `Spacer`, Intrinsic Widget'lar
- Bölüm 3 — Konu 10: MaterialApp/CupertinoApp, Scaffold, AppBar
- Bölüm 3 — Konu 11: `ListView`, `GridView`, `SingleChildScrollView` (+ Builder Pattern)
- Bölüm 3 — Konu 12: Text, TextStyle, Icon, Image, Asset Yönetimi
- Bölüm 3 — Konu 13: Custom Widget Yazma Prensipleri (Composition Over Inheritance)
- Bölüm 3 — Konu 14: Navigator 1.0 — Push/Pop, Named Routes
- Bölüm 4 — Konu 15: Form, TextField/TextFormField, GlobalKey<FormState>, Validasyon
- Bölüm 4 — Konu 16: Theme Sistemi (ThemeData, ColorScheme)
- Bölüm 4 — Konu 17: Responsive & Adaptive Tasarım (MediaQuery, LayoutBuilder, OrientationBuilder, Breakpoint Stratejileri)
- Bölüm 5 — Konu 18: Future/Async-Await Flutter Bağlamında, FutureBuilder
- Bölüm 5 — Konu 19: `Stream`, `StreamBuilder`
- Bölüm 5 — Konu 20: HTTP İstekleri (`http` / `dio` Paketleri)
- Bölüm 5 — Konu 21: JSON Serialization (Manuel → `json_serializable`/`freezed`)
- Bölüm 5 — Konu 22: Local Storage — `shared_preferences` → `Hive` → `sqflite`/Drift
- Bölüm 6 — Konu 23: InheritedWidget ve InheritedModel — "Neden setState Yetmiyor" Sorusunun Cevabı
- Bölüm 6 — Konu 24: Provider Paketi
- Bölüm 6 — Konu 25: Riverpod (Modern Yaklaşım, Provider'ın Halefi)
- Bölüm 6 — Konu 26: BLoC/Cubit Pattern (`flutter_bloc`)
- Bölüm 6 — Konu 27: GetX (Tartışmalı Ama Yaygın)
- Bölüm 6 — Konu 28: Karşılaştırma — Hangi Projede Hangisi?
- Bölüm 7 — Konu 29: Navigator 2.0 (Router, RouteInformationParser, RouterDelegate)
- Bölüm 7 — Konu 30: `go_router` Paketi (Pratik ve Modern Çözüm)
- Bölüm 7 — Konu 31: Deep Linking
- Bölüm 7 — Konu 32: Repository Pattern, Katmanlı Mimari (Data/Domain/Presentation)
- Bölüm 7 — Konu 33: Dependency Injection (`get_it`, `injectable`)
- Bölüm 7 — Konu 34: Clean Architecture Uyarlaması, SOLID Prensipleri
- Bölüm 8 — Konu 35: Implicit Animasyonlar
- Bölüm 8 — Konu 36: Explicit Animasyonlar (`AnimationController`, `Tween`, `Curve`)
- Bölüm 8 — Konu 37: Hero Animasyonları
- Bölüm 8 — Konu 38: `CustomPainter` / `Canvas`
- Bölüm 8 — Konu 39: Rive / Lottie Entegrasyonu
- Bölüm 9 — Konu 40: Platform Channels
- Bölüm 9 — Konu 41: Permission Yönetimi (`permission_handler`)
- Bölüm 9 — Konu 42: Kamera, Konum, Sensörler
- Bölüm 9 — Konu 43: Push Notification (Firebase Cloud Messaging)
- Bölüm 9 — Konu 44: Android/iOS Build Sistemleri
- Bölüm 10 — Konu 45: Test Yazımı (Unit, Widget, Integration, Golden)
- Bölüm 10 — Konu 46: CI/CD
- Bölüm 10 — Konu 47: Rebuild Optimizasyonu (`const`, `key` Kullanımı)
- Bölüm 10 — Konu 48: DevTools Profiling
- Bölüm 10 — Konu 49: Lazy Loading, Pagination, Büyük Liste Performansı
- Bölüm 11 — Konu 50: Firebase Ekosistemi (Auth, Firestore, Storage, Functions)
- Bölüm 11 — Konu 51: Supabase Alternatifi
- Bölüm 11 — Konu 52: GraphQL (Opsiyonel)
- Bölüm 11 — Konu 53: Store Yayınlama Süreci (İmzalama, Listing, Versiyonlama)
- Bölüm 11 — Konu 54: App Size, Obfuscation, Flavor Yönetimi
- Bölüm 12 — Konu 55: Flutter Web / Desktop
- Bölüm 12 — Konu 56: Custom `RenderObject` Yazımı
- Bölüm 12 — Konu 57: Engine Mimarisi Derinlemesine (Impeller vs Skia)
- Bölüm 12 — Konu 58: Plugin Geliştirme, pub.dev'e Paket Yayınlama
- Bölüm 12 — Konu 59: Monorepo Mimarisi (Melos)
- Bölüm 12 — Konu 60: Erişilebilirlik (Accessibility) Derinlemesine
- Bölüm 12 — Konu 61: Yerelleştirme (Localization / i18n)
İçindekiler 12 başlık
- Supabase Nedir? — "Açık Kaynaklı Firebase"
- NoSQL vs İlişkisel — Neden Önemli?
- Kurulum ve Temel Kullanım — Tanıdık Bir Desen
- Auth — Neredeyse Birebir Aynı Kavramlar
- Veritabanı — SQL Sorgusu Gibi Okunan, Ama Dart'ta Yazılan API
- Gerçek Zamanlı Veri — Stream ile
- Row Level Security (RLS) — Supabase'in Security Rules Karşılığı
- Edge Functions — Cloud Functions'ın Karşılığı
- Firebase vs Supabase — Karşılaştırma
- Ne Zaman Hangisini Seçersin?
- 🎯 Bu Dersten Çıkarılması Gerekenler
- 📝 Ödevler
Konu 50'de Firebase'i öğrendik — bu derste, aynı problemi farklı bir felsefeyle çözen Supabase'e bakacağız. Amaç, Supabase'i satır satır öğretmek değil (mekanik olarak Firebase'e çok benziyor), temel farkı anlaman: NoSQL vs ilişkisel (relational) veritabanı ayrımı.
Supabase Nedir? — "Açık Kaynaklı Firebase"
Supabase, kendini "open source Firebase alternative" olarak tanımlar — Auth, veritabanı, Storage, gerçek zamanlı veri, sunucu-taraflı fonksiyonlar gibi aynı kategorideki ihtiyaçları karşılar. Temel felsefe farkı: Firestore NoSQL (belge tabanlı) iken, Supabase'in veritabanı doğrudan PostgreSQL'dir — yani gerçek, ilişkisel bir SQL veritabanı.
NoSQL vs İlişkisel — Neden Önemli?
Konu 50'de Firestore'un veri modelini hatırla: koleksiyonlar ve belgeler, her belge kendi başına bir JSON nesnesi gibi. Supabase'de ise veri, tablolar, satırlar ve sütunlar halinde, klasik bir veritabanı gibi organize edilir:
-- Supabase'de bir tablo (SQL ile tanımlanır)
create table urunler (
id uuid primary key default gen_random_uuid(),
isim text not null,
fiyat numeric not null,
kategori_id uuid references kategoriler(id) -- İLİŞKİ (foreign key)
);references kategoriler(id) satırı, kritik farkı gösteriyor: Supabase'de tablolar arası ilişkiler (bir ürünün bir kategoriye ait olması gibi), veritabanının kendisi tarafından garanti edilir (bu, foreign key constraint olarak bilinir). Firestore'da bu tür ilişkiler, genelde elle (bir belgenin içine diğer belgenin ID'sini string olarak koyarak) yönetilir — veritabanı, bu ilişkinin geçerliliğini kendisi doğrulamaz.
Ne zaman hangisi daha uygun? Verin birbirine çok bağlıysa, karmaşık sorgular (örn. "geçen ay sipariş veren, İstanbul'da yaşayan, VIP kategorisindeki kullanıcılar") gerekiyorsa, ilişkisel bir veritabanı (Supabase) doğal olarak daha güçlüdür. Verin daha bağımsız, esnek şemalı belgelerden oluşuyorsa (her belgenin farklı alanları olabildiği, iç içe geçmiş yapılar), Firestore'un belge modeli daha rahat çalışır.
Kurulum ve Temel Kullanım — Tanıdık Bir Desen
flutter pub add supabase_fluttervoid main() async {
WidgetsFlutterBinding.ensureInitialized(); // Konu 43'ü hatırla
await Supabase.initialize(
url: 'https://senin-projen.supabase.co',
anonKey: 'senin-anon-anahtarin',
);
runApp(const MyApp());
}
final supabase = Supabase.instance.client; // uygulamanın her yerinden erişilebilirAuth — Neredeyse Birebir Aynı Kavramlar
Future<void> girisYap(String eposta, String sifre) async {
try {
await supabase.auth.signInWithPassword(email: eposta, password: sifre);
} on AuthException catch (hata) {
print('Giriş hatası: ${hata.message}');
}
}
// giriş durumunu STREAM olarak dinleme — Konu 50'deki authStateChanges() ile AYNI fikir
supabase.auth.onAuthStateChange.listen((veri) {
final oturum = veri.session;
print(oturum != null ? 'Giriş yapıldı' : 'Çıkış yapıldı');
});Dikkat ettiysen, kavramsal olarak Firebase Auth'tan hiçbir farkı yok — AuthException (Firebase'in FirebaseAuthException'ına karşılık), onAuthStateChange (Firebase'in authStateChanges()'ine karşılık). Bu tesadüf değil — her iki platform da aynı problemi çözüyor, sadece farklı isimlerle.
Veritabanı — SQL Sorgusu Gibi Okunan, Ama Dart'ta Yazılan API
// Veri okuma
final veri = await supabase
.from('urunler')
.select()
.eq('stokta', true) // Firestore'daki .where('stokta', isEqualTo: true) ile AYNI iş
.order('fiyat');
// Veri yazma
await supabase.from('urunler').insert({
'isim': 'Kablosuz Kulaklık',
'fiyat': 899.90,
});.from('urunler').select().eq(...).order(...) — bu method chaining kalıbı (Dart Bölüm 6'da öğrendiğimiz gibi, her metod this'i döndürerek zincirlemeye izin verir), arka planda gerçek bir SQL sorgusuna (SELECT * FROM urunler WHERE stokta = true ORDER BY fiyat) dönüştürülür. dio'nun (Bölüm 5 Konu 20) HTTP isteklerini kolaylaştırması gibi, Supabase'in Dart client'ı da, elle SQL yazmadan, SQL'in gücünü Dart'ın okunabilir bir API'si arkasında sunuyor.
Gerçek Zamanlı Veri — Stream ile
final urunAkisi = supabase
.from('urunler')
.stream(primaryKey: ['id'])
.eq('stokta', true);StreamBuilder<List<Map<String, dynamic>>>( // Firestore'daki QuerySnapshot yerine düz Map listesi
stream: urunAkisi,
builder: (context, snapshot) {
if (!snapshot.hasData) return const CircularProgressIndicator();
final urunler = snapshot.data!;
return ListView.builder(/* Bölüm 3 Konu 11 + Bölüm 10 Konu 49'u hatırla */);
},
)Firestore'un .snapshots()'ı ile tamamen aynı fikir — veritabanında bir değişiklik olduğunda, Stream otomatik olarak yeni veriyi yayınlar. Fark, dönen verinin tipinde: Firestore QuerySnapshot (kendi özel sarmalayıcı tipi) döndürürken, Supabase doğrudan List<Map<String, dynamic>> döner — Dart Bölüm 4'te öğrendiğimiz düz koleksiyon tiplerine daha yakın.
Row Level Security (RLS) — Supabase'in Security Rules Karşılığı
-- Supabase'de RLS politikası
create policy "Sadece giriş yapmış kullanıcılar yazabilir"
on urunler for insert
to authenticated
using (true);Konu 50'de Firestore'un Security Rules'unu öğrenmiştik — Supabase'in karşılığı Row Level Security (RLS), PostgreSQL'in kendi yerleşik bir özelliğidir (Supabase'e özgü değil, standart PostgreSQL). Aynı felsefe: client'a güvenilmez, her sorgu veritabanı seviyesinde kontrol edilir. Farkı, RLS'nin SQL diliyle (Firebase'in kendi kural dili yerine) yazılmasıdır — SQL bilen biri için daha tanıdık, ama öğrenme eğrisi biraz daha dik.
Edge Functions — Cloud Functions'ın Karşılığı
final sonuc = await supabase.functions.invoke('siparis-onayla', body: {'siparisId': '123'});Supabase'in Edge Functions'ı, Konu 50'deki Cloud Functions ile aynı işi görür — client'ta çalıştırılmaması gereken sunucu-taraflı mantık. Fark: Supabase Edge Functions Deno (bir JavaScript/TypeScript çalışma zamanı) üzerinde çalışır — yine TypeScript bilgisi gerektiriyor, senin planladığın öğrenme yoluna paralel ilerliyor.
Firebase vs Supabase — Karşılaştırma
| Firebase | Supabase | |
|---|---|---|
| Veritabanı modeli | NoSQL (belge/koleksiyon) | İlişkisel (PostgreSQL, SQL) |
| Karmaşık/ilişkili sorgular | Elle yönetilir, sınırlı | SQL'in tüm gücü mevcut |
| Açık kaynak | ❌ Hayır (Google'a bağımlı) | ✅ Evet (kendi sunucunda da barındırılabilir) |
| Sunucu-taraflı mantık | Cloud Functions (Node.js/Python) | Edge Functions (Deno/TypeScript) |
| Güvenlik modeli | Security Rules (kendine özgü dil) | Row Level Security (standart SQL) |
| Ekosistem olgunluğu | Çok olgun, geniş dokümantasyon | Daha genç ama hızla büyüyor |
| Push notification | Yerleşik (FCM) | Yok — ayrı bir servis (örn. FCM'i yine kullanabilirsin) |
Ne Zaman Hangisini Seçersin?
Firebase: Verin doğası gereği esnek/belge-tabanlıysa, push notification'ı aynı ekosistemden istiyorsan (Bölüm 9 Konu 43), ya da Google'ın geniş ekosistemine (Analytics, Crashlytics, Remote Config gibi burada değinmediğimiz araçlara) erişmek istiyorsan.
Supabase: Verin ilişkisel ve karmaşık sorgular gerektiriyorsa (bir e-ticaret, bir CRM gibi), SQL bilgisi (ya da öğrenme isteği) varsa, açık kaynak/vendor lock-in'den kaçınma önemliyse (kendi sunucunda da barındırabilirsin — Firebase'de bu mümkün değil).
Pratik gerçek: İkisi de API şekli olarak birbirine çok yakın (bu dersin gösterdiği gibi) — bir platformu öğrendikten sonra, diğerine geçiş kavramsal olarak zor değildir. Asıl karar, veri modelin (NoSQL mü, ilişkisel mi daha doğal) ve ekosistem tercihin (Google vs açık kaynak) etrafında döner.
🎯 Bu Dersten Çıkarılması Gerekenler
- Supabase, Firebase ile aynı problemleri (Auth, veritabanı, Storage, sunucu mantığı) çözer, ama veritabanı PostgreSQL (ilişkisel/SQL) tabanlıdır — Firestore'un NoSQL/belge modelinden temel farkı budur.
- Verin tablolar arası ilişkiler ve karmaşık sorgular gerektirdiği durumlarda, ilişkisel bir veritabanı doğal olarak daha güçlüdür.
- Auth, gerçek zamanlı veri (
Stream) gibi kavramlar, iki platform arasında neredeyse birebir eşlenir — farklı isimler, aynı fikir. - Row Level Security (RLS), Firestore'un Security Rules'una karşılık gelir, ama standart SQL ile yazılır.
- Firebase, geniş/olgun ekosistem ve esnek veri modeli sunar; Supabase, açık kaynak olma ve SQL'in gücünü sunar.
📝 Ödevler
- [ ] Bir Supabase projesi oluştur, e-posta/şifre ile giriş akışını kur, Konu 50'deki Firebase Auth koduyla satır satır karşılaştır.
- [ ] İki ilişkili tablo (örn.
urunlervekategoriler, foreign key ile bağlı) oluştur, bir sorguda ikisini birlikte çek (select('*, kategoriler(*)')gibi bir join sorgusu araştır). - [ ]
.stream()ile gerçek zamanlı bir liste kur, başka bir yerden (Supabase Studio arayüzünden) veri değiştirip anlık güncellendiğini doğrula. - [ ] Basit bir RLS politikası yaz, politika olmadan/olarak farkı gözlemle.
- [ ] Kendi cümlelerinle, "kendi projen için Firebase mi Supabase mi daha uygun olurdu" sorusuna, verinin doğasını (ilişkisel mi esnek mi) referans alarak cevap ver.
Sıradaki konu: Bölüm 11 — Konu 52: GraphQL (Opsiyonel)