🇬🇧 English: Read this article in English →
Gelip geçen bir sürü platform gördüm. Microsoft’un yığını üzerine kurulmuş, onlarca ajansın kullandığı kurumsal bir içerik sistemi işlettim. Vignette, Interwoven, FatWire ve Stellent’i, çoğu şirketin tüm BT bütçesinden daha pahalı oldukları yıllarda yakından inceledim. Ve içeriği bunların neredeyse hepsinden söküp aldım, ardından ne geldiyse onun üstüne taşıdım.
Strapi iyi bir araç. Başka bir şey söylemeden önce bunu söylemek istiyorum, çünkü internet, sana varacağın yeri satabilmek için ayrıldığın yeri yerin dibine sokan insanlarla dolu; ve ben bu yazıyı bunu yapmak için yazmadım. Strapi açık kaynak, Node.js tabanlı, geliştirici dostu bir araç ve popülerliğini dürüstçe kazandı. Eğer tek bir içerik kaynağından çok sayıda kanalı besliyorsan, headless CMS doğru mimaridir ve Strapi de meşru bir tercihtir.
Ama Strapi çalıştıran birçok ekip aslında tek bir kanalı besliyor — bir web sitesi — ve bunu yapmak için çok-kanallı bir mimarinin tüm bedelini ödüyor. O ekipler WordPress’e geçmeye karar verdiğinde, onları bundan caydırmaya çalışmam. Geri tepmesin diye planlamalarına yardım ederim.
Bu yazı işte o plan. Önce, kararı tartan herkes için genel çerçeve. Sonra, sona doğru, geçişin çalışıp çalışmayacağına ya da sessizce dağılıp dağılmayacağına asıl karar veren teknik ayrıntı.
Ekipler Strapi’yi neden bırakıp WordPress’e geçiyor
Strapi ve WordPress birbiriyle örtüşen sorunları çok farklı varsayımlarla çözüyor ve sürtünme genelde aynı yerlerde ortaya çıkıyor:
- İçerik ekibi geliştiricilere takılıp kalıyor. Strapi’de içerik modeli kodun içinde yaşar — Content-Types Builder şema dosyaları üretir ve her yapısal değişiklik, deploy edilmesi gereken bir kod değişikliğidir. Pazarlama bugün bir alan eklemek ya da bir landing page yayınlamak ister ama yapamaz, çünkü bu bir mühendislik işidir. WordPress’te, ACF ve blok editörüyle bunun büyük kısmı özerkleşir, kendi kendine hallolur.
- Operasyon. Strapi, senin barındırdığın, yamaladığın, ölçeklediğin ve ayakta tuttuğun bir Node uygulamasıdır. Bu, ekibinden birinin — çoğu zaman istemeye istemeye — sırtladığı gerçek bir operasyonel yük. WordPress barındırması ise çözülmüş, sıradanlaşmış bir sorun; fiyat üzerine rekabet eden binlerce sağlayıcı var.
- Ekosistem ve işe alım havuzu. WooCommerce, SEO eklentileri, formlar, üyelikler ve — en kritiği — aracı zaten bilen bir işgücü. Yarın bir WordPress’çi işe alabilirsin. Strapi yeteneği ise çok daha ince.
- Ömür. En çok tarttığım şey bu ve nedenini, kendimi iyi göstermek için anlatmadığım bir hikâyeyle açıklayacağım.
Sahiplik ve geçmişi taşımak üzerine bir hikâye
Yıllar önce, o dönemde WordPress’i kurumsal müşterilere satamadığım için — “kodu herkes görebiliyor” cümlesi bir özellik değil, bir güvenlik açığı gibi muamele görüyordu — ASPX üzerine kendi CMS’imizi kurduk. WordPress’i incelemiş ve iyi tasarlandığını bildiğimiz için modelimizi ona benzettik. Gerçekten iyi çıktı. Hızlıydı. Hiç tanışmadığımız onlarca ajans onun üstüne proje kurdu.
Ve sonra tamamen kendi hatamız olan bir duvara tosladık. CMS’imizin hiçbir geriye dönük uyumluluğu yoktu. Her yeni sürüm geçmişi unutuyordu. Bize göre sorun yoktu — biz hep en yeni build’deydik, hep ileri gidiyorduk. Ama onu kullanan herkes için her sürüm bir felaketti, çünkü verilerinin her seferinde elle taşınması gerekiyordu. O yükü taşıyamadık. Pes ettik. Büyük bir banka o sistemi bugün hâlâ çalıştırıyor, elle ayakta tutarak, çünkü biz çekip gittik ve onlar gidemedi.
WordPress’in neden hayatta kaldığını okuyarak öğrenmedim. Hayatta kalamayan sistemi kurarak öğrendim. Geriye dönük uyumluluk oyunun tamamı. Cazibesizdir, seni yavaşlatır ve on yıl önceki WordPress kodunun büyük kısmının hâlâ çalışırken, daha iyi finanse edilmiş platformların birer dipnota dönüşmesinin tek sebebi de odur.
Bu yüzden bir müşteri için platform seçtiğimde, ECM devlerinin müşterilerinin zamanında soramadığı soruyu sorarım: bu şirketi kim satın alabilir ve içeriğime bir gün sonra ne olur? Strapi açık kaynak ve bu gerçekten işe yarıyor — açık kaynağın olayı bedava olması değil, bir çıkış kapısının olması. Ama ekibinin bakımını yapamadığı, self-host edilen bir Node uygulaması da kendi türünden bir tuzaktır. WordPress’te hem çıkış kapısı hem de bakım havuzu var. Tek kanallı bir site için bu ikili, genellikle tartışmanın tamamıdır.
Geçişi nasıl planlıyorum
Herkeste gördüğüm hata, bunu bir export-import işi gibi ele almak. Değil. Bu, kılık değiştirmiş bir içerik-modelleme işidir ve işin tamamı o modellemede kazanılır ya da kaybedilir.
Ben matbaadan geliyorum; orada mizanpaj en son adımdır, önce yapı gelir. O disiplin beni hiç terk etmedi ve bir geçiş için de tam olarak doğru olan bu:
1. İçerik modelini eksiksiz envanterle. Her collection type, her single type, her component, her dynamic zone, her relation, her medya alanı. Gerçek şekli çiz. Haritasını çıkarmadığın şeyi taşıyamazsın.
2. Neyi geride bırakacağına karar ver. İki yıldır büyüyen bir Strapi modeli, kimsenin kullanmadığı component’ler ve “ne olur ne olmaz” diye eklenmiş relation’lar taşır. Geçiş, işe yaramayanları atmak için elindeki tek ruhsatlı fırsattır. Kurduğum her aşırı-tasarlanmış yapı sonunda ölü ağırlık çıktı; fazla basit diye burun kıvırdığım her fikir de işe yarayan fikir oldu. Sertçe buda.
3. Strapi’nin modelini WordPress’in modeline dürüstçe eşle. Collection type’lar custom post type’a dönüşür. Single type’lar options sayfalarına ya da tekil sayfalara dönüşür. Relation’lar ACF relationship alanlarına, post-to-post bağlantılarına ya da taxonomy’lere dönüşür. Component ve dynamic zone’lar ise — işin zor kısmı da bu — ACF flexible content ya da blok pattern’lerine dönüşür. Yerini hak etmeyen yapıyı düzleştirmeye gönüllü ol.
4. Önce WordPress’te boş hedefi kur. Post type’lar, ACF alan grupları, taxonomy’ler ve editörlerinin gerçekten kullanacağı blok pattern’ler. Gerçek içerik gelmeden önce, o yapının içinde yaşayacak insanlarla şekli doğrula.
5. Dönüştürücüyü yaz ve staging’de defalarca prova et. Asla doğrudan canlıya geçme. Yıllarımı disk basarak geçirdim ve bu işteki en kötü his, geri çağıramayacağın bir hatadır. Staging senin geri çağırma düğmen. Çıktı sıkıcılaşana kadar çalıştır.
6. Cutover’dan önce yönlendirmeler ve SEO. URL’lerin değişecek. Düğmeye basmadan önce eskiyi yeniye eşle, yoksa yılların sıralamasının bir haftada buharlaşmasını izlersin.
7. Cutover yap, sonra izlemeye devam et. Geçiş, içerik ekibi seni aramadan üç gerçek içeriği yayınladığında biter — bir dakika öncesinde değil.
Teknik Kısım: Strapi Geçişi Asıl Nerede Kırılıyor
Yukarıdaki her şey strateji. Asıl geçişin ayrıntılarda yaşayıp öldüğü yer burası. Eğer bunu yapan geliştirici sensen, önemli olan bölüm bu. İşte o özel tuzaklar.
Sen hangi rich-text alanındasın ki?
Strapi rich-text hikâyesini değiştirdi. Eski projeler zengin metni bir metin alanında Markdown olarak saklar. Yeni projeler, içeriği yapılandırılmış JSON olarak saklayan blocks rich-text alanını kullanır. Bunlar tamamen farklı biçimlerde taşınır:
- Markdown temiz biçimde önce HTML’e, sonra Gutenberg bloklarına dönüşür — bu kolay yol; bir Markdown-to-blocks adımı seni büyük ölçüde götürür.
- Blocks JSON, düğüm-düğüm (paragraflar, başlıklar, listeler, linkler, görseller) dolaşıp Gutenberg bloklarına eşlemen gereken iç içe geçmiş bir düğüm yapısıdır — ruhen soyut bir rich-text ağacını serialize etmeye daha yakın.
İşi tahminlemeden önce projenin hangisini kullandığını öğren, çünkü bunlar aynı iş değil. Ve her collection type’ı kontrol et — karışık projeler var; eski içerik Markdown, yeni içerik blocks olabilir.
Component ve dynamic zone’ların temiz bir WordPress karşılığı yok
Strapi geçişlerini yutan tuzak işte bu.
Bir Strapi component‘i, bir content type’ın içine gömülü, yeniden kullanılabilir bir alan grubudur. Bir dynamic zone ise editörün bir component listesinden seçip istediği sırada üst üste dizdiği bir alandır — özünde bir sayfa kurucu. WordPress core’da bunun birebir karşılığı yok.
Burada bilinçli bir mimari karar vermen gerekir ve otomatik bir cevabı yoktur:
- Dynamic zone’ları Gutenberg blok pattern’lerine eşle — her component bir bloğa ya da blok pattern’ine, zone da post’un blok içeriğine dönüşür. Bu, en native, en geleceğe dayanıklı sonuçtur ve en fazla iş çıkarandır.
- Dynamic zone’ları ACF flexible content’e eşle — her component bir flexible-content layout’una dönüşür. Strapi’nin kendi zihniyetine daha yakın, kurması daha hızlı; ama içeriğini editörde değil, meta’da tutar.
Hangisini seçersen seç, her component tipini elle ele almak zorundasın. Birini atlarsan, o içerik taşınan sayfalardan sessizce yok olur. Tek satır dönüştürme kodu yazmadan önce her component’i ve her dynamic-zone layout’unu envanterle. Bu, bir Strapi geçişinde en çok küçümsenen tek kalem — tüm taşınmaya bir hafta bütçe ayırıp, sonra içinde saklanan üç haftalık component eşlemesini bulan ekipler gördüm.
Relation’lar, sıralama ve iki-geçiş problemi
Strapi relation’ları — oneToOne, oneToMany, manyToMany — kayıtları ID üzerinden gösterir. WordPress’e import ettiğinde o ID’ler hiçbir şey ifade etmez. Ve bunları tek geçişte çözemezsin, çünkü kaynağı import ederken hedef kayıt henüz var olmayabilir.
İki geçişte yap: önce her kaydı import et ve Strapi ID’sini yeni WordPress post ID’sine eşleyen bir harita kur; sonra ikinci geçişte, o haritayı kullanarak her relation’ı ACF relationship alanlarına, post bağlantılarına ya da taxonomy terimlerine yeniden yaz. Orijinal Strapi ID’lerini, ikinci geçiş tamamlanana kadar post meta’da sakla.
Özellikle sıralamaya dikkat et. Strapi’deki many-to-many relation’lar çoğu zaman editörlerin elle ayarladığı anlamlı bir sıra taşır. Dönüştürücün bunu korumazsa, ilişkili öğeler karışık çıkar ve bir müşteri, öne çıkan ürünlerin yanlış sırada durduğu bir ana sayfayı gösterene kadar kimse fark etmez.
Medya URL’leri, sağlayıcılar ve yeniden yazma
Strapi’nin media library’si bir upload provider kullanır. Yerel modda dosyalar /uploads altında yaşar ve URL’ler görecelidir. Ama birçok canlı Strapi kurulumu Cloudinary, S3 ya da başka bir bulut sağlayıcı kullanır; o zaman medya URL’leri mutlak olur ve o sağlayıcının domain’ini gösterir.
Bundan iki şey çıkar. Birincisi, her varlığı gerçekte nerede yaşıyorsa oradan indirip WordPress media library’ye yeniden yüklemen gerekir. İkincisi — ve gözden kaçan da bu — rich-text içeriğinin içindeki her gömülü medya URL’sini yeniden yazman gerekir, çünkü Markdown ve blocks alanları eski sağlayıcı domain’ine sabitlenmiş linkler içerir. Bunu atlarsan, post’ların birazdan kapatacağın bir Strapi/Cloudinary hesabından görselleri sessizce yüklemeye devam eder. O hesap karardığında, tüm görsellerin de kararır.
Taslak ve yayın durumu
Strapi’nin bir draft-and-publish sistemi var ve Strapi 5’te Document Service, taslakları ve yayınlanmış sürümleri aynı dokümanın ayrı durumları olarak modelliyor. Export’un her şeyi filtrelemeden alırsa, bitmemiş taslakları canlı post’larmış gibi import edersin. Kuralı belirle — yalnızca yayınlananlar mı, yoksa taslaklar WordPress taslağı olarak mı — ve dönüştürme sırasında yayın durumuna göre filtrele.
Veriyi export etmek — strapi export kullanma
Yerleşik strapi export, Strapi’den Strapi’ye aktarım için tasarlanmış şifreli bir arşiv üretir. WordPress’e taşımak için işe yaramaz. Bunun yerine veriyi ya iç içe component ve relation’ları çekmek için populate ile REST API üzerinden çek, ya GraphQL eklentisi üzerinden, ya da — doğrudan veritabanı erişimin varsa ve şema kararlıysa — doğrudan alttaki Postgres veya MySQL’den al.
API yolunu seçersen sayfalama (pagination) limitlerine saygı göster. Strapi pageSize‘ı sınırlar ve her şeyi tek seferde isteyen naif bir export, kesilmiş bir kümeyi sessizce geri döndürür. Tüm 4.000 makaleyi taşıdığını sanırsın ama elinde sessizce 100 tane olur. Sayfala, say ve toplamları export’a güvenmeden önce kaynakla karşılaştır. Hangi yolu seçersen seç, veriyi bir dosyaya snapshot al ve dönüştürücünü o dondurulmuş kopyaya karşı çalıştır — canlı üretime karşı değil. Tekrarlanabilir, güvenle-başarısız-olabilen bir snapshot, işin tüm amacı zaten bu.
Strapi’de yaşayan iş mantığı
Strapi lifecycle hook’ları — content-type lifecycle dosyalarındaki beforeCreate, afterUpdate ve benzeri handler’lar — gerçek iş mantığı içerir: slug üretimi, denormalizasyon, bildirimler, doğrulama. Bunların hiçbiri içerikle birlikte taşınmaz. Ya WordPress hook’ları olarak yeniden yazılması gerekir, ya da sessizce çalışmayı bırakır. Lifecycle dosyalarını ve özel controller’larını erken envanterle; bu mantık veride görünmezdir ve otomatik gerçekleşen bir şey birden durana kadar unutulması kolaydır.
Frontend sözleşmesi değişir
Bugün bir Next.js, Nuxt ya da başka bir frontend Strapi’nin REST veya GraphQL API’sini tüketiyorsa, o frontend geçişten dokunulmadan çıkamaz. Artık WordPress REST API’sini ya da WPGraphQL’i tüketmek zorunda ve yanıt şekilleri tamamen farklı — Strapi’nin data/attributes zarfı ve populate edilmiş relation’ları, WordPress’in endpoint’lerine hiç benzemez. Frontend’in veri katmanını yeniden kurmaya ya da özel frontend’i emekliye ayırıp bir WordPress teması kullanmaya bütçe ayır. Bu sıklıkla en büyük gizli maliyettir ve müşterilerin en hazırlıksız yakalandığı kalemdir. İlk toplantıda yüksek sesle söyle.
Kullanıcılar ve izinler taşınmaz
Strapi’nin users-permissions eklentisi, temiz biçimde aktarılamayacak hesapları ve rolleri yönetir. Parola hash’leri sistemler arası taşınabilir değildir. Kullanıcıların parolalarını sıfırlamasını planla ve Strapi rollerini WordPress rollerine elle eşle. Sunamayacağın kesintisiz bir hesap geçişi sözü verme.
Dürüst kapanışım
Strapi’den WordPress’e geçmek, modern mimariden bir geri çekilme değildir. Tek kanallı bir web sitesi için bu bir doğru-boyutlandırmadır — çok sayıda ekran için kurulmuş bir sistemi ve birinin dadılık etmesi gereken bir Node uygulamasını, sıradan insanların ticket açmadan yayın yapabildiği, her yerde barındırılabilen, gerçekten işe alabileceğin bir işgücünün bakımını yapabildiği bir platformla takas etmektir.
Ama modelleme işine saygı göster, özellikle de component’ler ve dynamic zone’lara, çünkü saatlerin saklandığı yer orası. Ve WordPress’in en baştan neden varış noktası olduğunu unutma: trend olduğu için değil, geçmişi ileri taşıdığı için. Bu dersi zor yoldan öğrendim; taşımayan bir CMS kurarak ve taşıyamadığım için kendi kullanıcılarımı yüzüstü bırakarak.
Modeli haritala. İhtiyacın olmayanı buda. Her component’i ve her rich-text tipini elle ele al. Relation’ları iki geçişte yap ve sıralarını koru. Medya URL’lerini yeniden yaz. Lifecycle mantığını yeniden uygula. Staging’de seni sıkana kadar prova et. Cutover’dan önce yönlendirmelerini ayarla.
Bunu yap; içerik, doğru kalabileceği ve yaşayabileceği bir yere konsun — ki bu, otuz yıl ve CD-ROM’dan headless’e kadar her formattan sonra, bu işin hiç değişmemiş tek parçası olmaya devam ediyor.
Son Bir Şey: Peki Strapi’nin Yaptığını WordPress’le Yapamaz mısın?
Biri geçmeye karar verir vermez sorduğu ilk soru şu oluyor: Strapi’den çıkarsak, asıl sevdiğimiz headless modelden de vazgeçmek zorunda mıyız? Hayır. Değilsin. Ve WordPress’i hâlâ “sadece bir blog” sanan herkesin cidden şaşırdığı yer tam burası.
WordPress bu işe dün girmedi. REST API 2016 sonundan beri core’un içinde — neredeyse on yıldır sahada pişiyor. WPGraphQL da neredeyse o kadar eski; artık Automattic’in arkasında durduğu, WordPress’in kanonikleşme yolundaki GraphQL katmanı. Yani Strapi’nin sana verdiği şeyi — yapılandırılmış içeriğin, isteyen her arayüze JSON olarak dağıtılması — WordPress yıllardır, hem de göz önünde yapıyor. WPGraphQL ve REST API, Strapi’nin GraphQL ve REST endpoint’lerinin yerini birebir alır; ACF ve custom post types ise içeriğinin yaşadığı yer olarak collection type’larının, component’lerinin ve dynamic zone’larının yerini alır.
Demek ki Strapi’den çıkışın tek değil, iki dürüst yolu var:
- Klasik WordPress — bu yazının geri kalanı. Editörlere bir tema ver, ticket açmadan yayınlasınlar.
- Headless WordPress — sevdiğin decoupled mimariyi koru; sadece arkadaki motoru değiştir. İçerik deposu olarak WooCommerce, ACF ve custom post types ile WordPress, sorgu katmanı olarak WPGraphQL (ya da REST API) ve tepesinde zaten elindeki Next.js / Nuxt / Astro arayüzü — WPGraphQL-native bir framework istiyorsan Faust.js — eskisi gibi.
Asıl seni dik oturtacak kısım da şu. Zaten bir Node uygulamasını self-host ediyordun — yamalıyor, ölçekliyor, ona dadılık ediyordun. Headless WordPress de self-host edilir, ama tek başına ayakta tuttuğun çıplak bir servis değil; bir platform. Yani üstüne, Strapi’nin sana asla vermediği şeyleri kazanırsın.
- Gerçek bir ticaret motoru. WooCommerce. Headless-only bir Node CMS’e olgun bir mağazayı cıvatalamayı dene; hem özel kodun hem faturanın nasıl kabardığını izle.
- İnsanlar için editoryal güç — yalnızca geliştiriciler için değil: block editor, media library, revizyonlar, roller ve SEO’dan forma, üyelikten fazlasına uzanan bir eklenti ekonomisi; hiçbirini sıfırdan yazmıyorsun.
- Kullanıcı başı ücret yok, kullanım sayacı yok. Yüz editör ekle; fatura kıpırdamaz.
- Sahiplik. Bu serinin bütün argümanı — WordPress’i kimse ayağının altından satın alamaz.
WordPress’in burada yaptığı bazı şeyleri Strapi düpedüz yapmıyor — ticaret, eklenti ekonomisi, geliştirici olmayanlar için editörlük. Strapi iyi bir araç; en başta söyledim, arkasındayım. Ama “API üzerinden yapılandırılmış içerik istiyoruz” cümlesi WordPress’i geride bırakmak için bir sebep değil — WordPress’i headless çalıştırmak için bir sebep. Aşağıya geçmiyorsun. Ayakta tutmak zorunda olduğun çıplak bir Node servisini, aynı headless modele sahip, arkasında çok daha büyük bir alet çantası olan ve sahibini kimsenin belirleyemediği bir platformla takas ediyorsun.
İşte sürpriz bu. Headless ile WordPress arasında seçim yapmana gerek yoktu. İkisi birden senin olabilir.
Last modified: Temmuz 20, 2026
United States / English
Slovensko / Slovenčina
Canada / Français
Türkiye / Türkçe