Açık Kaynak Uygulamalar

    Payload CMS Nedir ve TypeScript Headless CMS Kurulumu

    TypeScript ve kod öncelikli yapılandırmasıyla öne çıkan modern açık kaynak headless CMS Payload rehberi.

    12 dk okuma Güncellendi: 10 Temmuz 2026

    Payload CMS, içerik modelini bir yönetim arayüzünde tıklayarak değil, doğrudan TypeScript kodu yazarak tanımladığınız modern bir açık kaynak headless CMS'tir. Geleneksel içerik yönetim sistemlerinin aksine burada koleksiyonlar, alanlar, erişim kuralları ve iş mantığı hep birlikte kod tabanında yaşar; yani içerik yapınız versiyon kontrolüne girer, kod incelemesinden geçer ve farklı ortamlar arasında güvenle taşınır. Payload çalıştığında bu tanımlardan hem eksiksiz bir REST ve GraphQL API'si hem de otomatik olarak üretilmiş, kullanıma hazır bir admin paneli çıkarır. Sonuçta hem geliştiricinin sevdiği kod disiplinini hem de içerik editörünün ihtiyaç duyduğu görsel arayüzü aynı anda elde edersiniz.

    Bu rehberde Payload'un neden "kod öncelikli" olarak anıldığını, koleksiyonların nasıl tanımlandığını, TypeScript tip güvenliğinin projeye kattığı somut faydayı ve veritabanı adaptörlerinden erişim kontrolüne kadar üretim seviyesinde bir kurulumun bütün parçalarını sırasıyla ele alacağız. Kıdemli bir sistem yöneticisi gözüyle, gerçek komutlar ve yapılandırma örnekleri üzerinden ilerleyeceğiz; ayrıca Payload'u Directus ve Supabase gibi alternatiflerle karşılaştırıp hangi senaryoda hangisinin daha mantıklı olduğunu netleştireceğiz.

    Headless CMS ve "Kod Öncelikli" Yaklaşım#

    Headless CMS, içeriğin depolanıp yönetildiği arka uç ile içeriğin gösterildiği ön uzu birbirinden ayıran bir mimaridir. Klasik WordPress kurulumunda tema, veritabanı ve yönetim paneli tek bir bütün olarak gelir; headless yaklaşımda ise CMS yalnızca içeriği bir API üzerinden sunar, o içeriği bir Next.js sitesinde mi, bir mobil uygulamada mı yoksa dijital tabelada mı göstereceğiniz tamamen size kalır. Bu ayrım, aynı içeriği birden fazla kanalda tekrar tekrar üretmek zorunda kalmadan kullanabilmenizi sağlar.

    Payload'u bu alandaki çoğu üründen ayıran şey "kod öncelikli" (code-first) felsefesidir. Directus veya Strapi gibi sistemlerde koleksiyonları genellikle bir yönetim arayüzünde alan alan tıklayarak oluşturursunuz; yaptığınız değişiklik doğrudan veritabanına yazılır. Payload'da ise içerik modelinin kaynağı bir yapılandırma dosyasıdır. Bir alanı eklemek, silmek ya da bir doğrulama kuralı yazmak, bir kod satırı değiştirmek anlamına gelir. Bu yaklaşımın pratik getirisi büyüktür: her şema değişikliği git geçmişinde görünür, pull request üzerinden gözden geçirilebilir, test ortamında denendikten sonra üretime taşınır. "Kim, ne zaman, hangi alanı değiştirdi" sorusunun cevabı artık tahmine değil kod geçmişine dayanır.

    Bu felsefe özellikle ekip halinde çalışan ve içerik yapısı sık değişen projelerde kendini gösterir. Görsel arayüzden yapılan şema değişiklikleri farklı ortamlar arasında elle senkronize edilmek zorunda kalırken, kod tabanlı şema doğal olarak dağıtım sürecinizin bir parçası olur. Aynı prensibi başka açılardan değerlendirmek isterseniz Directus incelememize göz atabilirsiniz; orada veritabanı öncelikli bir alternatifin nasıl çalıştığını görürsünüz.

    Payload Kurulumu ve İlk Proje#

    Payload en kolay şekilde resmi proje oluşturucu üzerinden başlatılır. Node.js 20 veya üzeri ve bir paket yöneticisi (npm, pnpm ya da yarn) yeterlidir. Aşağıdaki komut sizi birkaç soruyla karşılar; kullanmak istediğiniz veritabanını ve başlangıç şablonunu seçtirir.

    npx create-payload-app@latest cloutr-cms
    cd cloutr-cms
    

    Kurulum sihirbazı size boş bir proje mi yoksa blog gibi hazır bir şablon mu istediğinizi sorar, ardından veritabanı bağlantısını yapılandırmanızı ister. İşlem bittiğinde bağımlılıkları yükleyip geliştirme sunucusunu ayağa kaldırabilirsiniz.

    npm install
    npm run dev
    

    Geliştirme sunucusu varsayılan olarak 3000 portunda çalışır. Tarayıcıdan http://localhost:3000/admin adresine gittiğinizde ilk yönetici hesabını oluşturmanız istenir; bu hesabı oluşturduğunuz anda otomatik üretilmiş admin panelini karşınızda bulursunuz. API tarafında ise REST uç noktaları http://localhost:3000/api altında, GraphQL arayüzü de http://localhost:3000/api/graphql-playground altında hazır hâlde bekler.

    Ortam değişkenlerini .env dosyasında tutarsınız. En kritik iki değer veritabanı bağlantı adresi ve oturum şifrelemesinde kullanılan gizli anahtardır.

    DATABASE_URI=postgres://payload:parola@localhost:5432/cloutr_cms
    PAYLOAD_SECRET=uzun-ve-rastgele-bir-gizli-anahtar
    NODE_ENV=production
    

    PAYLOAD_SECRET değerini rastgele ve yeterince uzun tutmak güvenlik açısından zorunludur; bu anahtar sızarsa oturum tokenları taklit edilebilir. Üretim ortamında bu dosyanın sürüm kontrolüne girmediğinden emin olun. Payload'u kendi sunucunuzda barındıracaksanız, uygulamayı bir VDS sunucu üzerinde çalıştırıp önüne ters vekil olarak Nginx yerleştirmek en yaygın kurulumdur.

    Koleksiyonları Kod ile Tanımlamak#

    Payload'da her içerik türü bir "koleksiyon" olarak tanımlanır ve bu tanım saf bir TypeScript nesnesidir. Aşağıda basit bir blog yazısı koleksiyonu görüyorsunuz; alanların türleri, hangilerinin zorunlu olduğu ve admin panelinde nasıl görüneceği hep bu tek dosyada belirlenir.

    import type { CollectionConfig } from 'payload'
    
    export const Posts: CollectionConfig = {
      slug: 'posts',
      admin: {
        useAsTitle: 'title',
        defaultColumns: ['title', 'status', 'publishedAt'],
      },
      fields: [
        {
          name: 'title',
          type: 'text',
          required: true,
        },
        {
          name: 'slug',
          type: 'text',
          unique: true,
          index: true,
        },
        {
          name: 'status',
          type: 'select',
          defaultValue: 'draft',
          options: [
            { label: 'Taslak', value: 'draft' },
            { label: 'Yayında', value: 'published' },
          ],
        },
        {
          name: 'content',
          type: 'richText',
        },
        {
          name: 'publishedAt',
          type: 'date',
        },
      ],
    }
    

    Bu koleksiyonu ana yapılandırma dosyasına eklediğiniz anda üç şey aynı anda oluşur: admin panelinde "Posts" için tam işlevsel bir düzenleme ekranı belirir, /api/posts altında REST uç noktaları açılır ve GraphQL şemasına ilgili tipler eklenir. Bir alan eklemek için yalnızca fields dizisine yeni bir nesne koyarsınız; hiçbir arayüzde tıklamanıza, hiçbir veritabanı tablosunu elle değiştirmenize gerek kalmaz.

    Payload'un alan sistemi oldukça zengindir. Metin, sayı, tarih, seçim kutusu gibi temel türlerin yanında; başka koleksiyonlara relationship ile ilişki kurabilir, tekrar eden yapılar için array, esnek içerik blokları için blocks ve gruplu alanlar için group kullanabilirsiniz. Özellikle blocks alanı, editörün sürükle-bırak mantığıyla farklı içerik bölümlerini birleştirebildiği güçlü bir yapı sunar ve modern sayfa oluşturucularının temelini oluşturur. Medya dosyaları için ise upload tipli özel bir koleksiyon tanımlanır; Payload görselleri belirttiğiniz boyutlarda otomatik yeniden ölçekleyebilir.

    TypeScript Tip Güvenliğinin Getirdiği Somut Fayda#

    Payload'un en belirgin farkı, içerik modelinizden otomatik olarak TypeScript tipleri üretmesidir. Koleksiyonlarınızı tanımladıktan sonra tek bir komutla bütün içerik yapınızın tip tanımlarını dosyaya dökebilirsiniz.

    npm run payload generate:types
    

    Bu komut, projenizdeki her koleksiyon ve global için eksiksiz bir payload-types.ts dosyası üretir. Artık ön uçta bir yazıyı çektiğinizde post.title bir string, post.status yalnızca 'draft' veya 'published' olabilecek şekilde tiplenir. Var olmayan bir alana erişmeye kalktığınızda hata çalışma zamanında değil, kodu yazarken editörünüzde kırmızı çizgiyle belirir. Bu, büyük projelerde saatlerce süren "neden bu alan undefined geliyor" hata ayıklamalarını baştan ortadan kaldırır.

    Tip güvenliği yalnızca ön uçla sınırlı değildir. Payload'un kancaları (hooks), erişim fonksiyonları ve özel uç noktaları da bu tipleri kullanır. Örneğin bir yazı kaydedilmeden önce çalışan bir kancada, gelen verinin şeklini editörünüz zaten bilir; yanlış bir alan adı yazdığınızda derleme başarısız olur. Aşağıda bir yazı oluşturulmadan hemen önce slug alanını otomatik dolduran basit bir kanca örneği var.

    import type { CollectionBeforeChangeHook } from 'payload'
    
    export const fillSlug: CollectionBeforeChangeHook = ({ data }) => {
      if (data.title && !data.slug) {
        data.slug = data.title
          .toLowerCase()
          .replace(/[^a-z0-9]+/g, '-')
          .replace(/^-|-$/g, '')
      }
      return data
    }
    

    Bu tür iş mantığını CMS'in yönetim arayüzü ayarlarına gömmek yerine kod içinde tutmak, hem test edilebilirliği hem de takım içi paylaşımı kökten kolaylaştırır. Uygulama katmanı ile içerik katmanı aynı dilde, aynı tip sistemiyle konuştuğu için proje büyüdükçe yönetim yükü lineer değil, çok daha yavaş artar.

    Veritabanı Adaptörleri ve Depolama Seçimi#

    Payload verilerinizi doğrudan kendi seçtiğiniz veritabanında saklar; araya kapalı bir depolama katmanı koymaz. Bunu adaptörler aracılığıyla yapar ve projeyi kurarken hangi veritabanını kullanacağınızı belirlersiniz. Başlıca üç adaptör mevcuttur: PostgreSQL, MongoDB ve SQLite. Seçiminiz projenin ölçeğine ve mevcut altyapınıza göre değişir.

    AdaptörUygun SenaryoŞema YapısıNotlar
    PostgreSQLİlişkisel veri, raporlama, kurumsal projelerKatı, göç dosyalıDrizzle ORM tabanı; en güçlü sorgu desteği
    MongoDBEsnek şema, hızlı prototiplemeŞemasız belgeMongoose tabanı; iç içe veriye rahat
    SQLiteGeliştirme, küçük projeler, kenar dağıtımKatı, dosya tabanlıSunucu gerektirmez, tek dosyada çalışır

    PostgreSQL adaptörü kullanıyorsanız şema değişikliklerinizi göç (migration) dosyalarıyla yönetmeniz gerekir; bu üretim ortamında beklenmedik veri kaybını önler. Yeni bir göç oluşturmak ve uygulamak için şu komutları kullanırsınız.

    npm run payload migrate:create alan-eklendi
    npm run payload migrate
    

    Adaptör yapılandırması ana payload.config.ts dosyasında yapılır. PostgreSQL için tipik yapılandırma şöyle görünür:

    import { postgresAdapter } from '@payloadcms/db-postgres'
    import { buildConfig } from 'payload'
    
    export default buildConfig({
      db: postgresAdapter({
        pool: {
          connectionString: process.env.DATABASE_URI,
        },
      }),
      collections: [Posts, Media, Users],
    })
    

    Yüklenen dosyalar için yerel disk yerine bir S3 uyumlu nesne depolama kullanmak da mümkündür; büyüyen medya kütüphanelerinde bu önerilir. Kendi sunucunuzda barındırırken veritabanınızın düzenli yedeklenmesi kritik önemdedir; bu konuda otomatik yedekleme çözümlerimizi değerlendirebilirsiniz. Ayrıca içerik hacmi arttıkça veritabanı ile CMS'i ayrı süreçlerde ölçeklendirebilmeniz için yönetimli sunucu desteğinden yararlanmak yükünüzü hafifletir.

    Erişim Kontrolü ve Güvenlik#

    Payload'da yetkilendirme, koleksiyon başına yazdığınız erişim fonksiyonlarıyla yönetilir. Her fonksiyon, o an isteği yapan kullanıcıyı alır ve true, false ya da veriyi filtreleyen bir sorgu koşulu döndürür. Bu, "kim hangi kaydı okuyabilir, kim değiştirebilir" sorusuna kod seviyesinde ve tamamen özelleştirilebilir bir cevap vermenizi sağlar. Aşağıdaki örnekte yayındaki yazıları herkes okuyabilirken, taslakları yalnızca giriş yapmış kullanıcılar görebilir.

    export const Posts: CollectionConfig = {
      slug: 'posts',
      access: {
        read: ({ req: { user } }) => {
          if (user) return true
          return { status: { equals: 'published' } }
        },
        create: ({ req: { user } }) => Boolean(user),
        update: ({ req: { user } }) => Boolean(user),
        delete: ({ req: { user } }) => user?.role === 'admin',
      },
      fields: [ /* ... */ ],
    }
    

    Buradaki en güçlü nokta, read fonksiyonunun bir sorgu koşulu döndürebilmesidir. Yani "kullanıcı giriş yapmamışsa yalnızca yayındaki yazıları görsün" kuralı, uygulama katmanında elle filtreleme yapmanıza gerek kalmadan doğrudan veritabanı sorgusuna işlenir. Bu sayede yanlışlıkla gizli içeriğin API'den sızması gibi klasik güvenlik hataları büyük ölçüde engellenir.

    Erişim kontrolünü alan seviyesine kadar indirebilirsiniz; örneğin bir kullanıcının profilindeki e-posta alanını yalnızca kendisinin görmesini sağlayabilirsiniz. Payload ayrıca kimlik doğrulamayı yerleşik olarak sunar: kullanıcı koleksiyonuna auth: true eklediğinizde parola karması, oturum tokenları ve parola sıfırlama akışı otomatik gelir. Yine de bir CMS'i internete açtığınızda uygulama seviyesindeki bu korumaların önüne ağ seviyesinde bir savunma katmanı koymak akıllıcadır. Yönetim panelini kaba kuvvet saldırılarından korumak için önüne bir WAF yerleştirmek ve trafiği zorunlu olarak SSL sertifikası üzerinden şifrelemek, üretim kurulumunun ayrılmaz parçalarıdır.

    Payload'u Üretime Almak ve Ölçeklendirmek#

    Payload bir Node.js uygulaması olduğu için üretime alırken tipik bir Node servisini yönetir gibi davranırsınız. Uygulamayı önce derler, sonra süreç yöneticisiyle çalıştırırsınız. PM2 ya da systemd bu iş için yaygın seçeneklerdir.

    npm run build
    npm run start
    

    Uygulamanın önüne ters vekil olarak Nginx koymak hem SSL sonlandırma hem de statik dosya sunumu açısından standart bir tercihtir. Basit bir Nginx yapılandırması şöyle görünür:

    server {
        listen 80;
        server_name cms.example.com;
    
        location / {
            proxy_pass http://127.0.0.1:3000;
            proxy_http_version 1.1;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }
    

    Payload'u kendi sunucunuzda çalıştırmanın en büyük avantajı verinizin tamamen sizde kalması ve dış bir servise aylık ücret ödememenizdir; dezavantajı ise güncelleme, yedekleme ve ölçeklendirmenin sorumluluğunun size ait olmasıdır. Trafiğiniz arttığında Node sürecini yatay olarak çoğaltıp önüne bir yük dengeleyici koyabilir, veritabanını ayrı bir makineye taşıyabilirsiniz. Bu tür bir kurulum için bulut sunucu seçenekleri esneklik sağlar; küçük ve orta ölçekli projeler için ise tek bir sanal sunucu çoğu zaman fazlasıyla yeterlidir. DDoS gibi hacimsel saldırılara karşı bir DDoS koruma katmanı eklemek de kesintisiz erişim için önemlidir.

    Payload'u Directus ve Supabase ile Karşılaştırmak#

    Payload, Directus ve Supabase sık sık aynı listede anılır ama üçü farklı problemleri çözer. Payload kod öncelikli bir headless CMS'tir; içerik modelini geliştiriciye, editör deneyimini ise otomatik panele bırakır. Directus veritabanı öncelikli çalışır ve var olan bir veritabanının üzerine anlık bir yönetim katmanı ile API serer. Supabase ise bir CMS değil, PostgreSQL üzerine kurulu bir "backend platformu"dur; kimlik doğrulama, gerçek zamanlı abonelikler ve depolama gibi geniş bir servis yelpazesi sunar.

    ÖzellikPayloadDirectusSupabase
    YaklaşımKod öncelikli CMSVeritabanı öncelikli CMSBackend platformu
    Şema kaynağıTypeScript koduVeritabanı / panelSQL / panel
    İçerik editörü deneyimiZengin, otomatikZengin, esnekSınırlı (tablo odaklı)
    Tip güvenliğiYerleşik ve güçlüÜretilen tiplerÜretilen tipler
    İdeal kullanımİçerik ağırlıklı siteler, uygulamalarMevcut veritabanına APIUygulama arka ucu, gerçek zamanlı

    Seçim büyük ölçüde ekibinizin çalışma biçimine bağlıdır. TypeScript ile rahat çalışan, içerik yapısını versiyon kontrolünde tutmak isteyen ve editörlere cilalı bir panel sunmayı önemseyen ekipler için Payload çok güçlü bir tercihtir. Elinizde zaten dolu bir veritabanı varsa ve onun üzerine hızla bir yönetim arayüzü kurmak istiyorsanız Directus daha doğrudan bir yol sunar. İçerik yönetiminden çok kimlik doğrulama, gerçek zamanlı veri ve depolama gibi geniş bir arka uç ihtiyacınız varsa Supabase devreye girer. Bu üç aracın kurulumunu ve deneme sürecini kolaylaştırmak için App Center üzerinden tek tıkla kurulabilen sürümlere göz atabilirsiniz.

    Sıkça Sorulan Sorular#

    Payload CMS ücretsiz mi?#

    Payload'un kendisi açık kaynak ve ücretsizdir; MIT lisansıyla dağıtılır ve kendi sunucunuzda hiçbir lisans ücreti ödemeden kullanabilirsiniz. Yalnızca bulut barındırma hizmetini şirketin yönettiği Payload Cloud üzerinden almak isterseniz orada aylık bir ücret devreye girer, ancak self-hosted kullanım tamamen bedava kalır. Çoğu proje için tek maliyet, uygulamayı çalıştırdığınız sunucunun bedeli olur.

    Payload kullanmak için TypeScript bilmek zorunda mıyım?#

    Zorunlu değildir ama şiddetle önerilir çünkü Payload'un bütün gücü tip güvenliğinden gelir. Koleksiyonları düz JavaScript ile de tanımlayabilirsiniz, uygulama sorunsuz çalışır; ancak bu durumda otomatik üretilen tiplerin sağladığı hata yakalama ve editör desteği avantajını büyük ölçüde kaybedersiniz. Temel seviyede TypeScript bilmek, Payload'dan alacağınız verimi belirgin biçimde artırır.

    Payload hangi veritabanlarını destekler?#

    Payload üç ana veritabanı adaptörü sunar: PostgreSQL, MongoDB ve SQLite. PostgreSQL ilişkisel veri ve kurumsal projeler için en güçlü seçenektir, MongoDB esnek belge tabanlı yapısıyla hızlı prototiplemeye uygundur, SQLite ise geliştirme ve küçük dağıtımlar için ek bir sunucuya gerek bırakmaz. Adaptörü proje kurulumunda seçer ve daha sonra yapılandırma dosyasından değiştirebilirsiniz.

    Payload ile Directus arasındaki temel fark nedir?#

    En temel fark şema kaynağıdır: Payload içerik modelini TypeScript kodunda tutar, Directus ise doğrudan veritabanı yapısını temel alır ve şemayı panelden yönetir. Payload kodu esas aldığı için değişiklikler versiyon kontrolüne girer ve ortamlar arası taşıma kolaylaşır; Directus var olan bir veritabanının üzerine hızla API ve panel kurmak istediğinizde öne çıkar. Yani "kod odaklı disiplin mi, mevcut veritabanına hızlı erişim mi" sorusu seçimi belirler.

    Payload'u kendi sunucumda barındırabilir miyim?#

    Evet, Payload tamamen self-hosted çalışacak şekilde tasarlanmıştır ve zaten çoğu kullanıcı bu yöntemi tercih eder. Node.js 20 çalıştırabilen bir sunucu, bir veritabanı ve önüne konan bir ters vekil ile üretime hazır hâle gelir. Yönetimli bir altyapıda çalıştırmak isterseniz Clou.TR'nin sunucu ve yedekleme hizmetleri, güncelleme ve bakım yükünü omuzlarınızdan almak için uygun bir zemin sunar.

    Kapanış#

    Payload CMS, içerik modelini bir kod tabanı disipliniyle yönetmek isteyen modern ekipler için oldukça olgun ve güçlü bir seçenektir. Kod öncelikli yaklaşımı sayesinde şema değişiklikleriniz izlenebilir ve güvenli olur, TypeScript tip güvenliği hataları daha yazarken yakalar, otomatik üretilen admin paneli ise editörlerinizi yalnız bırakmaz. Esnek veritabanı adaptörleri ve kod seviyesindeki ince erişim kontrolüyle küçük bir blogdan kurumsal bir içerik altyapısına kadar geniş bir yelpazeye hitap eder.

    Payload'u ya da bu yazıda karşılaştırdığımız diğer headless CMS'leri kendi altyapınızda denemeye karar verirseniz, sağlam bir zemin işin yarısıdır. Yüksek performanslı VDS sunucularımız, tek tıkla kurulum sunan App Center çözümlerimiz ve güvenliği katmanlayan SSL ile yedekleme hizmetlerimizle projenizi ilk günden üretime hazır bir temele oturtabilirsiniz. İhtiyacınıza en uygun paketi seçmek için sunucu ve hosting seçeneklerimizi incelemeye başlayabilirsiniz.

    cmsapiself-hosted

    Uygulamaya geçmeye hazır mısınız?

    NVMe SSD, ücretsiz SSL ve %99.9 uptime garantisiyle Clou.TR hosting ve sunucu çözümleriyle projenizi hayata geçirin.