$npx -y skills add komunite/tezgah --skill saas-databaseSaaS uygulaması için Supabase veritabanı altyapısını kur. Proje oluşturma, şema tasarımı, Row Level Security (RLS), migration, connection pooling, realtime ve edge function yapılandırması. Bu skill'i kullanıcı veritabanı, Supabase, tablo, migration, RLS, şema veya veri modeli ile
| 1 | # SaaS Database — Supabase Veritabanı Altyapısı |
| 2 | |
| 3 | Bu skill, bir SaaS uygulamasının veritabanı katmanını kurar. Veritabanı uygulamanın belleğidir — şema kararları, güvenlik politikaları ve bağlantı stratejisi ilk günden doğru kurulmalıdır. |
| 4 | |
| 5 | **Bağımlılık:** Bu skill **saas-launcher** orkestratör skill'inin Faz 2'sinin derinleştirilmiş versiyonudur. Bağımsız olarak da kullanılabilir. |
| 6 | |
| 7 | **Bağlı skill'ler:** |
| 8 | - **saas-auth** — Kullanıcı modeli veritabanında tanımlanır. Auth, kullanıcı kaydını burada oluşturur. |
| 9 | - **saas-payments** — Abonelik ve plan bilgileri veritabanında saklanır. |
| 10 | - **saas-storage** — Dosya metadata'sı veritabanında, dosyanın kendisi Supabase Storage'da saklanır. |
| 11 | |
| 12 | --- |
| 13 | |
| 14 | ## Supabase Proje Kurulumu |
| 15 | |
| 16 | ### İlk Adımlar |
| 17 | |
| 18 | 1. https://supabase.com adresinden hesap oluştur |
| 19 | 2. Yeni proje oluştur — proje adı, veritabanı şifresi ve bölge seç |
| 20 | 3. Bölge seçimi: Kullanıcıların çoğunluğuna en yakın bölge. Türkiye için `eu-central-1` (Frankfurt) önerilir |
| 21 | 4. Dashboard'dan proje URL'si ve anon key'i al |
| 22 | 5. `.env.local` dosyasına ekle: |
| 23 | - `NEXT_PUBLIC_SUPABASE_URL` — proje URL'si (public, client'ta kullanılır) |
| 24 | - `NEXT_PUBLIC_SUPABASE_ANON_KEY` — anonim anahtar (public, RLS ile korunur) |
| 25 | - `SUPABASE_SERVICE_ROLE_KEY` — servis anahtarı (gizli, sadece server-side) |
| 26 | |
| 27 | **Kritik:** `SUPABASE_SERVICE_ROLE_KEY` asla `NEXT_PUBLIC_` prefix'i almamalı. Bu anahtar RLS'i bypass eder — client'a sızarsa tüm veriye erişim açılır. |
| 28 | |
| 29 | ### Supabase Client Kurulumu |
| 30 | |
| 31 | İki farklı client oluştur: |
| 32 | |
| 33 | **Browser client (client component'ler için):** Anon key ile çalışır, RLS kurallarına tabidir. Kullanıcının kendi verisine erişim için. |
| 34 | |
| 35 | **Server client (API route'ları ve server component'ler için):** Service role key ile çalışır, RLS'i bypass eder. Admin işlemleri, webhook handler'lar ve veri migration'ları için. |
| 36 | |
| 37 | **Middleware client:** Oturum yenileme ve auth kontrolü için. Edge Runtime uyumlu olmalı. |
| 38 | |
| 39 | Her client'ı ayrı bir dosyada tanımla ve projede tek yerden import et. Client'ları her dosyada yeniden oluşturma. |
| 40 | |
| 41 | --- |
| 42 | |
| 43 | ## Şema Tasarımı |
| 44 | |
| 45 | ### Temel Tablolar |
| 46 | |
| 47 | Her SaaS'ta olması gereken minimum tablolar: |
| 48 | |
| 49 | **users** — Kullanıcı profil bilgileri |
| 50 | - `id` (UUID, primary key — Supabase Auth'un user ID'si ile eşleşmeli) |
| 51 | - `email` (text, unique, not null) |
| 52 | - `full_name` (text) |
| 53 | - `avatar_url` (text, nullable) |
| 54 | - `plan` (text, default: 'free') |
| 55 | - `stripe_customer_id` (text, nullable, unique) |
| 56 | - `stripe_subscription_id` (text, nullable) |
| 57 | - `plan_expires_at` (timestamptz, nullable) |
| 58 | - `created_at` (timestamptz, default: now()) |
| 59 | - `updated_at` (timestamptz, default: now()) |
| 60 | |
| 61 | **Kullanıcı oluşturma tetikleyicisi:** Supabase Auth'a yeni kullanıcı kaydolduğunda `auth.users` tablosuna satır eklenir. Bu olayı dinleyen bir PostgreSQL trigger fonksiyonu yazarak `public.users` tablosuna otomatik kayıt oluştur. Bu sayede Auth ve veritabanı her zaman senkron kalır. |
| 62 | |
| 63 | **Ek tablolar (projeye göre):** |
| 64 | - `projects` / `workspaces` — Kullanıcının oluşturduğu kaynaklar |
| 65 | - `subscriptions` — Detaylı abonelik geçmişi |
| 66 | - `api_usage` — API kullanım sayaçları (plan limitleri için) |
| 67 | |
| 68 | ### Şema Tasarım İlkeleri |
| 69 | |
| 70 | - **UUID kullan.** Auto-increment integer yerine UUID — sıralı ID'ler güvenlik riski (tahmin edilebilir) ve multi-tenant uygulamalarda sorun yaratır. |
| 71 | - **Zaman damgası her tabloda olsun.** `created_at` ve `updated_at` her tabloya ekle. Debugging ve analitik için vazgeçilmez. |
| 72 | - **Soft delete düşün.** Kritik tablolarda `deleted_at` alanı ekleyerek silme yerine işaretle. Geri alma imkânı ve yasal uyumluluk (KVKK veri saklama süreleri) için. |
| 73 | - **İlişkileri foreign key ile zorunlu kıl.** Veritabanı seviyesinde ilişki bütünlüğü sağla. Uygulama koduna güvenme. |
| 74 | - **Index'leri erken ekleme.** İlk aşamada sadece foreign key ve sık sorgulanan alanlara index ekle. Geri kalanını sorgu yavaşlayınca ekle. |
| 75 | |
| 76 | --- |
| 77 | |
| 78 | ## Row Level Security (RLS) |
| 79 | |
| 80 | ### Neden Zorunlu |
| 81 | |
| 82 | RLS, Supabase'in en önemli güvenlik katmanıdır. Anon key client'ta açıkça görünür — RLS olmadan herhangi biri bu anahtarla tüm veriye erişebilir. |
| 83 | |
| 84 | **RLS'i her tabloda aktifleştir.** İstisnasız. RLS aktif değilse tablo herkese açıktır. |
| 85 | |
| 86 | ### Temel Politika Kalıpları |
| 87 | |
| 88 | **Kullanıcı kendi verisini görsün:** |
| 89 | - SELECT: `auth.uid() = user_id` koşulu ile |
| 90 | - INSERT: `auth.uid() = user_id` koşulu ile |
| 91 | - UPDATE: `auth.uid() = user_id` koşulu ile |
| 92 | - DELETE: `auth.uid() = user_id` koşulu ile (veya soft delete kullanıyorsan UPDATE) |
| 93 | |
| 94 | **Takım bazlı erişim:** |
| 95 | - Kullanıcının üye olduğu takımların verisine erişim |
| 96 | - `team_members` junction tablosu üzerinden kontrol |
| 97 | |
| 98 | **Public okuma, authenticated yazma:** |
| 99 | - Blog yazıları, |