Production SaaS Starter
Çok Kiracılı SaaS Platformu
Workspace tabanlı çok kiracılık, Stripe faturalama, platform admin, RBAC ve i18n içeren production odaklı B2B SaaS temeli. Bu rehber sizi klonlamadan yerel çalıştırmaya bir saatten kısa sürede götürür.
Genel bakış
Production SaaS Starter, workspace tabanlı çok kiracılı bir platformdur — minimal bir demo değil. Gerçek kalıplar içerir: PostgreSQL RLS, SECURITY DEFINER RPC'ler, Stripe webhook idempotency, çift katmanlı RBAC ve servis sağlayıcı soyutlaması.
- Üyelikler, davetler ve slug kapsamlı URL'lerle workspace'ler
- Stripe abonelikleri, kullanım ölçümü, promosyon kodları ve kurumsal anlaşmalar
- Denetim günlükleri ve kullanıcı/workspace moderasyonu ile platform admin konsolu
- E-posta/şifre + OAuth, 2FA, Resend ile şifre sıfırlama
Stack: Next.js 16, React 19, Supabase, Stripe, Resend, 4 dil ile next-intl.
Bağımlılıkları yükle
Ortam değişkenlerini yapılandırmadan önce proje kökünden npm paketlerini yükleyin.
Depoyu klonladıktan sonra bir kez çalıştırın:
npm installOrtam kurulumu
Veritabanı migrasyonlarından veya uygulamayı çalıştırmadan önce .env.local dosyasını yapılandırın. Önce dosyayı oluşturun, ardından kurulum ilerledikçe bölüm bölüm değer ekleyin.
Yerel env dosyası oluştur
Örnek dosyayı kopyalayın — Stripe ve Resend değerlerini aşağıdaki bölümlerde ekleyin. Supabase değişkenleri Supabase kurulum bölümünde yapılandırılır.
cp .env.example .env.localUygulama
ZorunluDağıtılmış uygulama URL'niz — ödeme yönlendirmeleri, e-posta bağlantıları ve OAuth callback'leri için kullanılır.
Adımlar
- 1Yerel geliştirme için NEXT_PUBLIC_APP_URL=http://localhost:3000 ayarlayın
- 2Production için Vercel dağıtım URL'nizi veya özel alan adınızı kullanın
- 3Değişkeni Vercel → Proje → Ayarlar → Ortam Değişkenleri bölümüne ekleyin
Ortam değişkenleri
NEXT_PUBLIC_APP_URLZorunluSaaS uygulamanızın genel URL'si (sonunda / olmadan).
Nerede bulunur
Yerel: http://localhost:3000 · Production: Vercel proje alan adı veya özel domain
Örnek: https://app.alanadiniz.com
NEXT_PUBLIC_APP_NAMEİşlemsel e-postalarda gösterilen marka adı.
Nerede bulunur
Herhangi bir görünen ad seçin — harici servis gerekmez
Örnek: Acme SaaS
Supabase kurulumu
Bu Supabase adımlarını sırayla tamamlayın — proje oluşturma, ortam değişkenleri ve veritabanı migrasyonu.
Bu Supabase adımlarını sırayla tamamlayın — proje oluşturma, ortam değişkenleri ve veritabanı migrasyonu.
7 adım — sırayla tamamlayın
Supabase kurulumu
~5 dkProjenizi oluşturun ve Project ID'nizi kopyalayın
Supabase projesi oluştur
supabase.com'da oturum açın, New project'e tıklayın, ad ve bölge seçin, veritabanı parolası belirleyin ve sağlanmayı bekleyin.
Supabase Panelini açProject ID'nizi kopyalayın
CLI bağlantısı ve API URL oluştururken kullanılacak.
Supabase ortam değişkenleri
Supabase projenizi oluşturduktan sonra .env.local dosyasına ekleyin — veritabanı migrasyonlarından önce.
NEXT_PUBLIC_SUPABASE_URLProje API URL'niz. YOURPROJECTID yerine gerçek Supabase Project ID'nizi yazın.
NEXT_PUBLIC_SUPABASE_URL=https://YOURPROJECTID.supabase.coNerede bulunur
Supabase Panel → Project Settings → API
NEXT_PUBLIC_SUPABASE_ANON_KEYGenel anon anahtar — tarayıcıda güvenle kullanılabilir. Panelden kopyalayın; yer tutucu kullanmayın.
Nerede bulunur
Supabase Panel → Project Settings → API
SUPABASE_SERVICE_ROLE_KEYYalnızca sunucu tarafı. İstemciye asla açmayın. Panelden kopyalayın; yer tutucu kullanmayın.
Nerede bulunur
Supabase Panel → Project Settings → API
Veritabanı kurulumu ve migrasyonlar
~15 dkCLI kurulumu, bağlantı ve şema migrasyonu
Supabase CLI yükle
Global yükleyin, ardından doğrulayın:
npm install -g supabaseKurulumu doğrula:
supabase --versionSupabase CLI'ye giriş yap
Kimlik doğrulama için bir tarayıcı penceresi açılır. Giriş yapın ve terminale dönün.
supabase loginYerel projeyi bağla
PROJECT_REF yerine 2. adımdaki Project ID'nizi yazın.
supabase link --project-ref <PROJECT_REF>Örnek:
supabase link --project-ref abcdefghijklmnopVeritabanı migrasyonlarını uygula
Tüm tabloları, fonksiyonları, politikaları ve seed verilerini oluşturur. Supabase kimlik bilgileri .env.local'de olmalıdır.
supabase db pushTabloların oluşturulduğunu doğrula
Devam etmeden önce şemanızın hazır olduğunu onaylayın.
Veritabanını güncelleme
Veritabanı değişiklikleri içeren repo güncellemelerini çektikten sonra:
git pull
supabase db pushStripe kurulumu
Stripe CLI
Geliştirme sırasında yerel kimlik doğrulama ve webhook yönlendirme için Stripe CLI kullanın.
- 1Resmi Stripe dokümantasyonundaki talimatlara göre Stripe CLI'yi yükleyin
- 2Platforma özel kurulum adımlarını tamamlayın
- 3Stripe kimlik doğrulama/giriş işlemini çalıştırın
- 4Kimlik doğrulamadan sonra yerel Stripe geliştirmesine devam edin
CLI'yi doğrula
login çalıştırın — Stripe hesabınızı bağlamak için bir tarayıcı penceresi açılır:
stripe loginWebhook'ları yerelde yönlendir
Ayrı bir terminalde olayları yerel webhook işleyicinize yönlendirin. İmza secret'ını STRIPE_WEBHOOK_SECRET'e kopyalayın:
stripe listen --forward-to localhost:3000/api/stripe/webhookAPI anahtarları
Anahtarları Stripe panelinden .env.local dosyasına kopyalayın — depoda veya dokümantasyonda asla hardcode etmeyin.
Nerede bulunur
Stripe Panel → Developers → API Keys
- Publishable Key (pk_test_...)
- Secret Key (sk_test_...)
Ortam değişkenleri
STRIPE_SECRET_KEYZorunluSunucu tarafı Stripe API anahtarı — panelden kopyalayın, asla hardcode etmeyin.
Nerede bulunur
Stripe Panel → Developers → API Keys — Secret key (sk_test_...)
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEYZorunluStripe.js checkout için istemci tarafı anahtar — panelden kopyalayın, asla hardcode etmeyin.
Nerede bulunur
Stripe Panel → Developers → API Keys — Publishable key (pk_test_...)
Webhook'lar
Adımlar
- 1Yerel geliştirme için stripe listen --forward-to localhost:3000/api/stripe/webhook çalıştırın ve webhook imza secret'ını kopyalayın
- 2Dağıtılmış ortamlar için webhook endpoint ekleyin: https://YOUR_APP_URL/api/stripe/webhook
- 3Olayları seçin: checkout.session.completed, customer.subscription.*, invoice.*, payment_method.*
- 4Webhook imza secret'ını .env.local içinde STRIPE_WEBHOOK_SECRET'e kopyalayın
Ortam değişkenleri
STRIPE_WEBHOOK_SECRETZorunluStripe webhook imzalarını doğrular.
Nerede bulunur
Stripe Panel → Developers → Webhooks → Signing secret · Yerel: stripe listen çıktısı
Resend kurulumu
Resend
Zorunluİşlemsel e-posta — davetler, 2FA OTP, şifre sıfırlama. Supabase yerleşik e-postası kullanılmaz.
Adımlar
- 1resend.com'da kayıt olun
- 2Gönderim alan adınızı ekleyin ve doğrulayın (DNS kayıtları)
- 3Bir API anahtarı oluşturun
- 4RESEND_FROM_EMAIL'i alan adınızda doğrulanmış bir adrese ayarlayın
Ortam değişkenleri
RESEND_API_KEYZorunluE-posta göndermek için API anahtarı.
Nerede bulunur
Resend Panel → API Keys → Create API Key
RESEND_FROM_EMAILZorunluDoğrulanmış gönderici adresi (örn. noreply@alanadiniz.com).
Nerede bulunur
Resend Panel → Domains → Alan adı ekle → DNS doğrula → o alandaki bir adresi kullanın
Hızlı başlangıç
Yukarıdaki ortam, Supabase, Stripe ve Resend kurulumunu tamamladıktan sonra bu komutları sırayla çalıştırın:
Proje bağımlılıklarını yükle
npm installSeed planlarını Stripe ile senkronize et — ağırlıklı olarak test ve Stripe planlarını veritabanıyla eşitlemek için
npm run sync:plansGeliştirme sunucusunu http://localhost:3000 adresinde başlat
npm run devGeliştirme ve production
Günlük geliştirme ile production derlemesini yerelde önizleme için farklı komutlar kullanın.
Geliştirme
Hot reload ile geliştirme sunucusunu başlatın:
npm run devProduction önizlemesi
Production ortamını yerelde önizleyin — uygulamayı derleyin, ardından production sunucusunu başlatın:
npm run buildnpm run startKomut referansı
| Komut | Açıklama |
|---|---|
| supabase db push | Veritabanı şemasını uygula (supabase db push) |
| npm run sync:plans | Seed planlarını Stripe ürün/fiyatlarıyla senkronize et |
| npm run dev | Geliştirme sunucusunu başlat |
| npm run build | Production derlemesi |
| npm run start | Production sunucusunu başlat (build sonrası) |
| npm run test | Jest birim testlerini çalıştır (yalnızca servisler) |
Mimari
Katı çağrı sırası olan dört katman — agent'lar ve geliştiriciler aynı yolu izler:
UI → Server Actions / API → Services → Repositories → PostgreSQL (RLS/RPC)Temel konumlar:
Katman 1
Sunum — src/app/, src/components/
Katman 2
Uygulama — server action'lar, createRequestContext(), RBAC guard'ları
Katman 3
Domain — src/modules/*/ *.service.ts (iş kuralları)
Katman 4
Veri — repository'ler + src/services/ üzerinden PostgreSQL RLS/RPC'ler
Çok kiracılık
Workspace kiracıdır — ayrı bir organizasyon tablosu yoktur.
- Kiracı anahtarı: workspaces.id (UUID); URL'ler benzersiz slug kullanır
- Üyelikler kullanıcıları owner, admin veya member rolleriyle workspace'lere bağlar
- RLS politikaları workspace_id IN (kullanıcının üyelikleri) kuralını uygular
Platform admin'ler platform_admins tablosu üzerinden /admin'e erişir — super_admin, platform_admin veya platform_viewer rolleri.
Kimlik doğrulama ve yetkilendirme
Auth akışı: giriş → isteğe bağlı 2FA → onboarding (workspace yok) veya workspace paneli. Platform admin davetleri platform-onboarding'e yönlendirir.
- Supabase Auth ile e-posta/şifre ve OAuth
- E-posta OTP ile 2FA (Resend) — Supabase yerleşik e-postası değil
- Token tabanlı akış ve hız sınırlama ile şifre sıfırlama
Workspace rolleri ve izinleri:
ownerfaturalama, workspace silme, tam üye yönetimiadminüye davet etme/çıkarma, workspace ayarlarını güncellemememberokuma ve katılım — admin işlemi yok
Faturalama ve abonelikler
Workspace başına bir aktif abonelik, Stripe müşteri ve abonelik ID'lerine bağlı.
- Yeni abonelikler için checkout; self-servis yönetim için portal
- Orantılı yükseltmeler; dönem sonunda planlanan düşürmeler
- Seed planlar: Starter ($29/ay), Pro ($39/ay), Enterprise (özel)
- /api/stripe/webhook, idempotent stripe_events tablosu ile durumu senkronize eder
Dağıtım
Önerilen stack: Vercel (Next.js) + Supabase Cloud + Stripe webhook'ları.
- 1Production Supabase'e şemayı uygulayın (supabase db push)
- 2Tüm env değişkenlerini Vercel'de ayarlayın — yukarıdaki Ortam kurulumu bölümünü kullanın
- 3Next.js uygulamasını dağıtın
- 4Stripe webhook kaydedin → https://UYGULAMA_URL/api/stripe/webhook
- 5Production'da super admin oluşturun ve sync:plans çalıştırın

