Astro, Paddle ve Cloudflare ile Modern Bir Membership Platformu

Astro 5, Paddle subscription, Supabase ve Cloudflare edge computing ile kurumsal düzeyde bir içerik ve kurs platformu nasıl inşa edilir? Mimari kararlar, entegrasyonlar ve Claude Code iş akışı.

Ceyhun Enki Aksan
Ceyhun Enki Aksan Girişimci, Maker

Modern teknolojiler, edge computing ve AI-destekli geliştirme ile kurumsal düzeyde bir membership platformu.

Bu yazı, Astro 5, Paddle ve Cloudflare Pages ile nasıl ürünleştirilebilir bir membership platformu inşa edileceğini anlatmaktadır. Astro’nun static site generation gücünü, Paddle’ın subscription yönetimini ve Cloudflare’in edge computing altyapısını bir araya getirerek performans, güvenlik ve geliştirici deneyimini optimize eden bir mimari sunuyorum.

Amacım, tek başıma geliştirdiğim ve geliştirme sürecinde Claude Code, içeriklerin Grav CMS’den Astro’da uygun hale getirilmesinde LM Studio aracılığı ile local olarak kullandığım Qwen ile birlikte yönettiğim bu sistemi, benzer ihtiyaçları olan geliştiriciler için yeniden kullanılabilir bir şablona dönüştürmek. Geleneksel blog veya CMS’lerin ötesinde, tier-bazlı erişim kontrolü, premium içerik gating ve otomatik webhook işleme gibi kurumsal özellikler barındırır.

Neden Bu Mimari?

Modern bir içerik platformu kurarken üç temel zorlukla karşılaşırsınız:

  1. Performans vs Dinamik İçerik: Statik siteler hızlıdır ama üyelik sistemleri dinamik bileşenler gerektirir
  2. Ödeme Entegrasyonu: Subscription yönetimi, webhook’lar, fatura ve vergi karmaşıklığı
  3. Global Dağıtım: Düşük latency, CDN ve edge computing gereksinimleri

Bu mimari, bu problemleri hibrit bir yaklaşımla çözer:

  • Statik sayfalar Astro ile build-time’da oluşturulur (hız)
  • Dinamik API’ler Cloudflare Pages Functions ile edge’de çalışır (esneklik)
  • Subscription mantığı Paddle’a devredilir (karmaşıklık dışarıda)
  • Veritabanı Supabase ile yönetilir (gerçek zamanlı, güvenli)

Teknoloji Stack’i

Frontend ve Build

TeknolojiVersiyonKullanım Amacı
Astro5.15.2Static Site Generator + Edge Functions
TypeScript5.9.3Type-safe geliştirme
TailwindCSS3.4.17Utility-first CSS
MDX4.3.9Markdown + JSX bileşenleri
Pagefind1.4.0Client-side arama indeksleme

Backend ve Servisler

TeknolojiKullanım Amacı
SupabasePostgreSQL veritabanı, authentication, real-time
PaddleSubscription yönetimi, ödeme, fatura
Cloudflare PagesHosting, edge functions, global CDN
Cloudflare KVKey-value cache (arama, premium içerik)
Cloudflare R2Object storage (görseller, assets)

Proje Yapısı

ceaksan-v4.0/
├── src/
│   ├── components/              # 68+ Astro bileşeni
│   │   ├── pages/               # Sayfa-spesifik bileşenler
│   │   ├── ui/                  # UI component library
│   │   └── sections/            # Yeniden kullanılabilir bölümler
│   ├── content/                 # Astro Content Collections
│   │   ├── posts/               # Blog yazıları (MDX)
│   │   └── courses/             # Video kursları
│   ├── lib/                     # 52 library modülü
│   │   ├── paddle/              # Paddle entegrasyonu
│   │   ├── supabase.ts          # Server-side client
│   │   └── supabase-browser.js  # Browser client
│   ├── pages/                   # File-based routing
│   └── styles/                  # Global stiller
├── functions/                   # Cloudflare Pages Functions
│   └── api/                     # 15 API endpoint
├── .claude/                     # Claude Code entegrasyonu
│   ├── commands/                # Slash commands
│   ├── subagents/               # Specialized agents
│   └── hooks/                   # Automatic hooks
└── public/                      # Static assets

Astro Konfigurasyonu

Astro 5 ile çalışırken kritik bir kural var:

Asla output: 'hybrid' kullanmayın. Çünkü, bu mod Astro 5 ile artık mevcut değil.

Cloudflare Free Tier Challenge

Bu projede önemli bir karar noktası vardı: Cloudflare’in resmi Astro adapter’ını kullanmamak. Neden?

Cloudflare Pages’in free tier’ı belirli build limitlerine sahip. @astrojs/cloudflare adapter’ı kullanıldığında, adapter’ın ihtiyaç duyduğu bağımlılıklar ve build süreci bu limitleri zorluyordu. Detaylar için Cloudflare’in Astro rehberine bakılabilir.

Adapter kullanmadan çözüm:

// astro.config.mjs
export default defineConfig({
  output: 'static',  // KRİTİK: Her zaman 'static'

  i18n: {
    defaultLocale: 'tr',
    locales: ['tr', 'en'],
    routing: {
      prefixDefaultLocale: true  // /tr/page ve /en/page
    }
  }
  // NOT: Cloudflare adapter KULLANILMIYOR
});

Bu Yaklaşımın Artıları ve Eksileri

Artıları:

  • Cloudflare free tier içinde kalabilme
  • Daha küçük build çıktısı
  • Daha hızlı build süreleri
  • Daha az bağımlılık

Eksileri:

  • Cloudflare-spesifik özellikler (Image CDN, vb.) doğrudan kullanılamıyor
  • Server-side rendering için manuel functions/ dizini yönetimi
  • Adapter’ın sağlayacağı otomatik optimizasyonlardan mahrum kalma

Dinamik Sayfalar

Dinamik sayfalar için functions/ dizininde Cloudflare Pages Functions kullanılır:

// functions/api/example.ts
export const onRequest: PagesFunction = async (context) => {
  // KV, R2, D1 erişimi burada mümkün
  return new Response(JSON.stringify({ data }));
};

Astro sayfaları için ise sayfa bazında prerender devre dışı bırakılabilir:

// Dinamik sayfa örneği
export const prerender = false;

Bu yaklaşımın avantajları:

  • Statik sayfalar build-time’da oluşturulur (hızlı, ucuz)
  • Dinamik sayfalar edge’de çalışır (KV, R2 erişimi)
  • Bundle boyutu optimize edilir (gereksiz SSR kodu yok)
  • Free tier limitleri içinde kalıyor

Paddle Subscription Entegrasyonu

Tier Sistemi

Platform üç katmanlı bir üyelik sistemi sunar:

TierErişim
Insiderİçerikler
Makerİçerik + Dosyalar + Kodlar
MasterHer Şey + Kurslar

Kritik Kural: Kurs erişimi sadece Master tier ile mümkündür. Bu, price_id bazlı doğrulanır—tier ismi değil. Çünkü, zaman içerisinde tier adı değişebilir ancak Paddle tarafında price_id korunur.

Webhook İşleme

Paddle webhook’ları /api/paddle/webhook endpoint’inde işlenir:

// Webhook event types
- subscription.created    // Yeni abonelik
- subscription.updated    // Plan değişikliği
- subscription.canceled   // İptal
- transaction.completed   // Ödeme onayı

Her webhook event’i:

  1. İmza doğrulaması yapılır
  2. webhook_events tablosuna loglanır
  3. subscriptions tablosu güncellenir
  4. Idempotency için event_id kontrol edilir

Subscription Güncelleme Mantığı

// Upgrade: Anında, prorated
proration_billing_mode: 'prorated_immediately'

// Downgrade: Sonraki dönem
proration_billing_mode: 'prorated_next_billing_period'

// İptal: Dönem sonuna kadar erişim devam eder
effective_from: 'next_billing_period'

Supabase Veritabanı Mimarisi

Supabase, platformun temel veritabanı altyapısını oluşturur:

  • Müşteri yönetimi: Kullanıcı bilgileri ve Paddle entegrasyonu
  • Abonelik takibi: Subscription durumu, plan bilgisi, faturalama
  • Kurs kayıtları: Enrollment yönetimi ve erişim kontrolü

Row Level Security (RLS) ile her tablo güvenlik altında. Kullanıcılar sadece kendi verilerine erişebilir.

Erişim Kontrolü Akışı

1. Kullanıcı premium içeriğe erişmek ister
2. Auth check → Supabase session
3. Tier validation → price_id bazlı kontrol
4. Sonuç: İçerik göster veya paywall

Cloudflare Entegrasyonu

KV Namespaces (6 adet)

NamespaceKullanım
PREMIUM_CONTENTPremium post içerikleri
COURSE_CONTENTKurs içerikleri
ANALYTICSKullanım metrikleri
FEATURE_FLAGSÖzellik bayrakları
RATE_LIMITERRate limiting
SESSIONSession yönetimi

R2 Object Storage

Bucket: your-assets
URL: https://assets.your-domain.com
Kullanım: Görseller, dosyalar, medya

API Endpoints

Platform, Cloudflare Pages Functions üzerinde çalışan API’ler içerir:

  • Paddle entegrasyonu: Webhook işleme, subscription yönetimi
  • İçerik erişimi: Premium içerik ve kurs delivery
  • Fiyatlandırma: Dinamik fiyat bilgisi

Pagefind ile Arama

Algolia veya ElasticSearch yerine Pagefind tercih edildi:

  • Client-side arama: Sunucu maliyeti yok
  • Build-time indeksleme: Otomatik
  • Çok dilli destek: TR ve EN ayrı indeksler
  • Küçük bundle: ~100KB
// Build sonrası otomatik indeksleme
// dist/pagefind/ klasöründe oluşturulur

// Arama kullanımı
const pagefind = await import('/pagefind/pagefind.js');
await pagefind.init();
const results = await pagefind.search('astro');

Son güncelleme ile Pagefind araması header’daki arama butonuna bağlanmış durumda. Kullanıcı arama butonuna tıkladığında Pagefind modal’ı açılır ve dil bazlı filtreleme otomatik olarak uygulanır.

Premium İçerik Gating

Frontmatter ile Tier Belirleme

---
title: "Premium İçerik"
requiredTier: ['insider']  # Array formatında
member: true
---

Client-Side Access Check

import { checkContentAccess } from '@/lib/content-access-client.js';

const hasAccess = await checkContentAccess(getSupabaseClient, {
  requiredTier: ['insider'],
  onAccessGranted: () => showContent(),
  onAccessDenied: () => showPaywall()
});

Premium İçerik Delivery

Premium içerikler client-side render edilmez. API üzerinden fetch edilir:

// /api/content/premium-post
// 1. Auth check
// 2. Tier validation
// 3. KV'den içerik fetch
// 4. Render edilmiş HTML döndür

i18n (Çok Dilli Destek)

URL-Based Routing

/tr/contents/   → Türkçe içerikler
/en/contents/   → English contents

Dil Algılama

const lang = window.location.pathname.startsWith('/en') ? 'en' : 'tr';
const text = lang === 'tr' ? 'Türkçe Metin' : 'English Text';

Content Collections

src/content/posts/2026/01/01.slug/
├── tr.mdx    # Türkçe versiyon
└── en.mdx    # İngilizce versiyon

Claude Code Entegrasyonu

Verification-First Approach

Give Claude a way to verify its work — Boris Mann

Bu prensip, Claude Code ile geliştirmenin temelini oluşturur. Her değişiklik doğrulanabilir olmalı.

Slash Commands

Projede tanımlı slash command’lar:

/test-and-build     - Testleri çalıştır, build yap
/verify-changes     - Kapsamlı doğrulama
/commit-push-pr     - Commit + Push + PR oluştur
/preview-deploy     - Preview ortamına deploy
/kv                 - KV yönetimi

Custom Skills

.claude/commands/ klasöründe tanımlı skill’ler:

  • test-and-build.md: Build ve test otomasyonu
  • verify-changes.md: Değişiklik doğrulama
  • preview-deploy.md: Preview deployment
  • kv.md: KV namespace yönetimi

Her skill, Claude Code’un belirli görevleri tutarlı ve doğrulanabilir şekilde yapmasını sağlar.

Hooks

Otomatik çalışan hook’lar:

.claude/hooks/
├── PostToolUse.sh   # Her kod değişikliğinde formatting
└── AgentStop.sh     # Her agent bitişinde doğrulama

CLAUDE.md Kuralları

Projeye özel kurallar CLAUDE.md dosyasında tanımlı. Bu dosya Claude Code’un proje kurallarını anlamasını sağlar:

## KRİTİK KURALLAR

### NO HARDCODED VALUES
// YANLIŞ:
const price = '$49.99'
const planName = 'Tier 2 - Profesyonel'

// DOĞRU:
API'den dinamik fetch
Database'den gerçek değerler

Bu yaklaşım, hardcoded değerlerin koda sızmasını engeller ve tutarlı bir geliştirme deneyimi sağlar.

Build ve Deployment

npm Scripts

# Development
npm run dev                 # Dev server

# Build
npm run build              # Production build
npm run build:kv-data      # Search KV data
npm run build:premium-kv   # Premium content KV

# Deployment
npm run deploy:pages       # Cloudflare Pages
npm run preview           # Local preview

Build Süreci

1. Astro build → dist/
2. Pagefind indeksleme → dist/pagefind/
3. KV data generation (opsiyonel)
4. Cloudflare Pages deployment

Performans Optimizasyonları

Bundle Optimization

// Vite config
- Manuel chunk splitting (supabase, paddle ayrı)
- Asset inline limit: 0 (asla inline etme)
- CSS immutable (1 yıl cache)

Image Optimization

  • Sharp ile build-time optimizasyon
  • R2 CDN delivery
  • Lazy loading
  • WebP/AVIF formatları

KV Caching

- Arama içeriği: PREMIUM_CONTENT içinde
- Premium postlar: PREMIUM_CONTENT
- Kurs içerikleri: COURSE_CONTENT

Güvenlik

Headers

Content-Security-Policy: [detaylı CSP]
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin

Rate Limiting

// RATE_LIMITER KV namespace
// API endpoint bazlı throttling

Webhook Signature Verification

// Paddle webhook'ları imza ile doğrulanır
const isValid = verifyPaddleSignature(request, secret);

Metrikler

MetrikDeğer
Astro Version5.15.2
Components68+
API Endpoints15
KV Namespaces6
Dil Desteği2 (TR, EN)
Subscription Tiers3
Build Output~200MB

Sonuç

Bu mimari, modern web teknolojilerinin bir araya geldiği, ürünleştirilebilir bir membership platformu şablonu sunmaktadır:

  • Performans: Astro SSG + Cloudflare edge
  • Esneklik: Hybrid rendering, dinamik API’ler
  • Ölçeklenebilirlik: KV caching, R2 storage
  • Güvenlik: CSP, rate limiting, webhook verification
  • Geliştirici Deneyimi: Claude Code, slash commands, hooks
  • Maliyet Optimizasyonu: Cloudflare free tier limitleri içinde

Cloudflare free tier’ında kalarak maliyet-verimli bir çözüm oluşturmak mümkün. Ancak bu, resmi adapter’ın bazı avantajlarından vazgeçmeyi gerektiriyor. Bu nedenle, projeyi ürünleştirdiğimde iki farklı paket halinde sunacağım. Gelişmelerle ve güncellemelerle ilgili takipte kalmak isterseniz X üzerinden beni takip edebilirsiniz.

Özet geçmek gerekirse, Ne yaptım? Blog kurmadım, yeniden kullanılabilir bir platform şablonu oluşturdum. Kime hitap ediyor? Benzer bir membership sistemi kurmak isteyen geliştiricilere. Neden farklı? Çünkü performans, güvenlik ve maliyet dengesi aynı anda düşünüldü.