🇬🇧 English: Read this article in English →

Otuz yıldır içeriği bir yerden alıp başka bir yere taşıyorum. CD-ROM’lar, Flash, bir evden pahalıya patlayan kurumsal içerik yönetim sistemleri ve nihayetinde web. Biçim durmadan değişiyor. İş hiç değişmiyor: içeriği doğru yere ulaştır, doğru tut, yaşat.

O yüzden biri bana Sanity’den çıkıp WordPress’e geçmek istediğini söylediğinde ne şaşırıyorum ne de satış konuşması yapıyorum. 1996’dan beri sorduğum aynı soruyu soruyorum — o zamanlar bir veritabanını plastik bir diske basıp güncelleyemiyordum: bu içeriğin gerçekte nereye gitmesi gerekiyor ve kim onu ticket açmadan değiştirebilmeli?

O soru her şeyi belirliyor. Bu yazı, bir Sanity-WordPress geçişini nasıl düşündüğüm üzerine — önce kararı tartan herkes için sade bir dille, sonra da sona doğru, geçişin başarılı mı olacağını yoksa sessizce mi çürüyeceğini asıl belirleyen teknik ayrıntıda.

Önce Sanity’ye hakkını vereyim

Buraya sana Sanity kötü demeye gelmedim. Gerçekten iyi kurulmuş bir headless CMS. Yapılandırılmış içerik, GROQ’ta gerçek bir sorgu dili, sayfa olarak değil veri olarak modellenmiş içerik, gerçek zamanlı iş birliği ve geliştiricilerin saygı duyduğu bir editör deneyimi. Eğer tek bir içerik kaynağından altı ekranı besliyorsan — bir web sitesi, bir mobil uygulama, mağaza içi ekranlar, dijital fiyat etiketleri, bir kiosk, bir iş ortağı API’si — headless doğru mimaridir ve Sanity ciddi bir seçimdir. Seni bundan caydırmam.

Ben headless’ı adı daha konmadan istiyordum. Doksanlarda bir üniversite tercih asistanı yaptım ve onu gazete ekindeki bir CD-ROM’da dağıttım. Bir kontenjan değiştiğinde disk çoktan yüz bin evdeydi, eski rakam içinde donmuş hâlde. İçeriğin tek bir yerde durmasını, ihtiyaç duyan hangi ekransa ona ulaşmasını ve dağıtım katmanına hiç dokunmadan güncellenebilmesini istiyordum. Sanity’yi 1996’da istiyordum ve kuramıyordum, çünkü altyapı henüz yoktu.

Yani bu fikre burun kıvıracak son kişi benim.

Ekipler Sanity’yi WordPress uğruna gerçekte neden terk ediyor

İşte defalarca sahnelenişini izlediğim rahatsız edici gerçek: headless CMS çalıştıran çoğu kuruluş tam olarak tek bir kanalı besliyor — bir web sitesini. İçeriği kendi ön kapılarına ulaştırmak için koca bir dağıtım sistemi satın aldılar.

Ve bu mimarinin tam bedelini ödüyorlar. İçerik ekibi, bir geliştirici şema kodunu değiştirip deploy etmeden bir alan bile ekleyemiyor. Yapıya dokunan her editoryal ince ayar bir pull request’e dönüşüyor. Preview başlı başına ayrı bir proje. İçeriği yazan insanlar, kodu deploy eden insanlara sürekli bağımlı. Çok sayıda kanalı beslerken bu gayet iyi bir takas. Tek bir web sitesini beslerken kötü bir şaka.

Bu yüzden ekipler nadiren teknik olan sebeplerle WordPress’e geçiyor:

  • Editoryal bağımsızlık. Pazarlama ekibi bir alan eklemek, bir sayfayı yeniden sıralamak, cuma öğleden sonra bir kampanya için landing page yayınlamak istiyor — bir mühendislik sprint’ini beklemeden.
  • Maliyet ve bağımlılık. Sanity’nin fiyatı kullanımla ve koltuk sayısıyla ölçekleniyor ve her içerik değişikliği bir geliştirici maliyeti taşıyor. Tek kanallı bir sitede bu matematik anlamını yitiriyor.
  • Ekosistem. WooCommerce, Yoast ya da RankMath, formlar, üyelikler, devasa bir eklenti ekonomisi ve aracı zaten bilen koca bir istihdam havuzu.
  • Uzun ömürlülük. En çok önemsediğim bu ve buna geri döneceğim.

O son maddeyi açıkça söyleyeyim, çünkü asıl inandığım şey bu. Platformlar teknik başarısızlıktan nadiren ölür. Sahiplikten ölürler. Vignette, Interwoven, FatWire, Stellent — 2000’lerin başındaki her ciddi ECM platformunu — satın alınırken, yutulurken, adı değiştirilirken ve sessizce raflara kaldırılırken izledim. Hiçbiri yazılım kötü olduğu için ölmedi. Öldüler çünkü birileri şirketi satın aldı ve senin içerik stratejin, hiç danışılmadığın bir entegrasyon planının bir satır kalemine dönüştü.

Sanity, iyi fonlanmış özel bir şirket. Sonunu öngörmüyorum. Ama bir müşteri için platform seçerken şunu soruyorum: bu şirketi kim satabilir ve içeriğim o satışın ertesi günü ne olur? WordPress satın alınamaz. Kimse sahibi değil — Automattic bile. Bu küçük bir özellik değil. Pek çok ekip için tek başına bütün argüman zaten bu.

Geçişi nasıl planlıyorum — çoğu insanın atladığı kısım

Her geçişteki en büyük hata, onu bir export-import problemi gibi görmek. Değil. O, export-import kostümü giymiş bir içerik-modelleme problemi.

Ben matbaadan geliyorum ve matbaa bana dijitalcilerin nadiren öğrendiği bir şey öğretti: her zaman biçimden önce yapı. O yüzden tek bir satır geçiş koduna dokunmadan önce şunu yapıyorum:

1. İçerik modelinin envanterini çıkar. Her Sanity doküman tipi, her alan, her referans, Portable Text’inin içindeki her özel obje. Muğlak bir liste değil — gerçek bir harita. Şeyi taşımadan önce şeklini görmek istiyorum.

2. Neyi taşımayacağına karar ver. Bu, herkesin direndiği ve atladığına herkesin pişman olduğu adım. Üç yılda büyümüş bir içerik modeli; kimsenin kullanmadığı alanlarla, çoktan biten bir kampanya için yaratılmış doküman tipleriyle ve bir editör ihtiyaç duyduğu için değil, bir geliştirici titiz davrandığı için var olan yapılarla dolu. Geçiş, bir şeyleri atmana izin verilen tek an. Fırsatı değerlendir. Fazla basit diye reddettiğim her fikir sonunda sattı; aşırı-mühendislikle kurduğum her yapı sonunda ölü ağırlık çıktı. Acımasızca buda.

3. Sanity’nin modelini WordPress’in modeline eşle — dürüstçe. Bu iki sistem farklı düşünür. Sanity, tamamen veri olarak yapılandırılmış içeriktir. WordPress ise metaveriye sahip bir post’tur. Bu farkla savaşmak, geçişlerin ölme biçimidir. Ayrıntılara aşağıda gireceğim ama planlama ilkesi şu: her Sanity doküman tipini bir WordPress post tipine ya da sayfaya, her alanı native bir alana, bir ACF alanına ya da bir taxonomy’ye eşle ve masrafını çıkarmayan yapıyı düzleştirmeye razı ol.

4. Hedefi önce WordPress’te kur — boş hâliyle. Custom post type’lar, ACF alan grupları, taxonomy’ler, editörlerinin gerçekten kullanacağı blok pattern’leri. Tek bir satır gerçek içerik gelmeden önce, şekli doğru kur ve içinde yaşayacak insanlara doğrulat.

5. Transform’u yaz, sonra staging’de deneme koşusu yap. Tekrar tekrar. Asla doğrudan production’a geçiş yapma. Asla. Geçimimi CD-ROM basarak sağladım ve sana şunu söyleyebilirim: bu işteki en kötü his, geri çağıramayacağın bir hatadır. Staging deneme koşusu senin geri-çağırma düğmen. Çıktı sıkıcılaşana kadar kullan.

6. Yönlendirmeler ve SEO, geçişten sonra değil önce. URL yapın değişecek. Eski yolları yenilerine eşlemezsen, yıllarca inşa ettiğin sıralamaların bir haftada buharlaştığını izlersin.

7. Geçişi yap, sonra izle. Geçiş, cutover’da bitmez. İçerik ekibi seni aramadan üç gerçek şey yayınladığında biter.

Zamanlama üzerine bir söz, çünkü araçlardan daha çok önemli

CD-ROM turizm başlıklarımın haklarını, teklif edildikleri gecenin aynısında sattım, çünkü biçimin bittiğini görebiliyordum. Ne zaman hamle yapacağını bilmek, geride bıraktığın şeyde mükemmel olmaktan daha değerlidir.

Aynısı burada da geçerli. Bu çeyrekte headless modası geçti diye Sanity’den çıkma; ve geçiş yapmak bir hatayı itiraf etmek gibi hissettiriyor diye de onda kalma. Kanallarını say. Dürüst cevap “bir web sitesi” ise, o sofistike mimari, sahip olmadığın bir sorunu çözen bir makinedir ve WordPress’e geçmek bir düşüş değil — doğru ölçeklendirmedir. Dürüst cevap “altı ekran ve büyüyor” ise, olduğun yerde kal ve okumayı bırak.


Teknik Kısım: Sanity Geçişi Asıl Nerede Kırılıyor

Yukarıdaki her şey strateji. İşte geçişin ayrıntılarda başardığı ya da battığı kısım. İşi yapan geliştirici sensen, yazdırıp önüne koyacağın bölüm bu. Bunlar, geçişleri tek lokmada yuttuğunu izlediğim tuzaklar.

Bütün savaş Portable Text

Sanity, zengin metni HTML olarak saklamaz. Onu Portable Text olarak saklar — bir blok obje dizisi; her biri children (marks taşıyan span’ler), link gibi annotation’lar için bir markDefs dizisi, bir style (normal, h2, blockquote) ve en kritiği, satır içine gömülmüş keyfi özel _type objeleriyle: görseller, kod blokları, callout’lar, embed’ler, ürün referansları.

WordPress ise zengin metni Gutenberg blok işaretlemesi olarak saklar — blok-sınırlayıcı yorumlarla bezeli HTML. Bu iki format birbirine otomatik eşlenmez ve aralarındaki boşluk, sadakatin öldüğü yerdir.

İki dürüst seçeneğin var:

  • Portable Text’i HTML’e serialize et (@portabletext/to-html gibi bir kütüphaneyle) ve onu bir core/freeform ya da core/html bloğuna bırak. Hızlı, ama blok-native editör deneyimini kaybedersin — içeriğin tek bir opak HTML yumrusu olarak gelir.
  • Blok blok native Gutenberg bloklarına eşlenormal stilindeki Portable Text block‘unu core/paragraph‘a, h2‘yi core/heading‘e, blockquote‘u core/quote‘a, liste öğelerini core/list‘e, gömülü görsel objelerini core/image‘a, kod objelerini core/code‘a. Çok daha fazla iş ve editörler bu içeriğe dokunmaya devam edecekse doğru cevap bu.

Seni asıl ısıracak şey ise özel mark’lar ve gömülü objeler. Her projede vardır — bir highlight mark’ı, satır içi bir ürün referansı, bir callout objesi, bir akordeon. Bunlar için otomatik çeviri yoktur. Her biri için, WordPress’te neye dönüşeceğine karar vermek ve handler’ı yazmak zorundasın. Bir tanesini atla, ya sessizce yok olur ya da yayınlanmış post’una ham JSON olarak dökülür. Tek bir serializer yazmadan önce Portable Text’indeki her _type‘ın envanterini çıkar.

Görsel hotspot ve crop metaverisi kaybolacak

Sanity görselleri yalnızca dosya değildir. Her görsel referansı hotspot ve crop metaverisi taşır ve Sanity’nin görsel CDN’i bunları her istekte anlık uygular. WordPress’te buna denk bir kavram yok. Orijinalleri indirip medya kütüphanesine ittiğinde, hotspot ve crop verisi gider. Özenle sanat yönetimi yapılmış crop’ların, temanın varsayılan olarak ne yapıyorsa ona geri döner.

Buna açıkça hazırlan. Ya kaybı kabul edip önemli görselleri yeniden crop’la ya da crop’ları export edilen dosyalara pişir ki en azından birincil rendition doğru olsun. Bunu cutover’dan sonra, müşteri her hero görselinin neden yanlış ortalandığını sorduğunda keşfetme.

Draft katmanı ve drafts. öneki

Sanity, yayınlanmamış düzenlemeleri _id‘sinde drafts. önekiyle ayrı dokümanlar olarak saklar. Düzenlediğin bir doküman iki kez var olur: drafts.abc123 (senin çalışma kopyan) ve abc123 (yayınlanmış sürüm). Export’un her şeyi safça kaparsa ikisini de import edersin — ve mükerrer post’lar elde edersin, biri yayınlanmış içerik kılığına girmiş bitmemiş bir taslak.

Kuralını baştan belirle: yalnızca yayınlanmışları taşı ya da taslakları WordPress taslağı olarak taşı. Sonra transform sırasında _id önekine göre filtrele. Bu, kaçırırsan iki günlük temizliğe yol açan iki satırlık bir düzeltme.

Referanslar, slug’lar ve iki-geçişli problem

Sanity içeriği ilişkiseldir — dokümanlar diğer dokümanlara _ref ile referans verir. Bir makale yazarına referans verir; bir ürün kategorisine referans verir. WordPress’e import ettiğinde, o referanslar WordPress için hiçbir anlam ifade etmeyen Sanity _id‘lerini gösterir.

Referansları tek geçişte çözemezsin, çünkü kaynağı import ederken hedef henüz var olmayabilir. İki geçişte yap: önce her dokümanı import et ve Sanity _id‘sinden yeni WordPress post ID’sine bir harita kur; sonra ikinci bir geçişte, o haritayı kullanarak her referansı yeniden yaz — ACF ilişki alanlarına, post-to-post bağlantılarına ya da taxonomy terimlerine. İkinci geçiş bitene kadar her import edilen öğede _id ve _type‘ı sakla (post meta’da). Sıralamayı yanlış yaparsan, ilişkilerin sessizce yanlış post’ları gösterir.

Slug’lar da aynı özeni ister. Yönlendirme haritanın aklı başında kalması için Sanity slug’larını mümkün olduğunca koru ve çakışmalara dikkat et — Sanity slug’ları doküman tipi başına benzersizdir ama WordPress slug’ları tipler arasında çakışabilir.

Export mekaniği

sanity dataset export <dataset> <file.tar.gz> kullan. Her dokümanın bir NDJSON dosyasını, artı bir asset paketini (ya da CDN’den çözülebilir asset referanslarını) üretir. Production’a karşı canlı GROQ sorgularından değil, o dosyadan çalış — transform’unu API’yi hırpalamadan ya da hareketli bir hedef kovalamadan yüz kez tekrar koşabileceğin donmuş bir anlık görüntü istiyorsun. O donmuş anlık görüntü, senin doğru yapılmış kırk dakikalık CD basma işin: kasıtlı, tekrarlanabilir ve karşısında hata yapmaya güvenli.

Arayüz sözleşmesi değişir

Şu an bir Next.js ya da Nuxt arayüzü Sanity’den GROQ ile veri çekiyorsa, o arayüz geçişten dokunulmadan çıkamaz. Artık WordPress REST API’sini ya da WPGraphQL’i tüketmesi gerekiyor ve verinin şekli tamamen farklı. GROQ projection’ları ile WordPress’in endpoint’leri birbirinin yerine geçmez. Arayüzün veri katmanını yeniden kurmaya ya da özel arayüzü tümden emekliye ayırıp bir WordPress teması kullanmaya bütçe ayır. Bu çoğu zaman en büyük gizli maliyettir ve müşterilerin en çok şaşırdığı kalemdir. Onu son toplantıda değil, ilk toplantıda gündeme getir.

Yerelleştirme (localization)

Sanity’nin uluslararasılaştırmasını kullandıysan — ister doküman-bazlı ister alan-bazlı — WordPress karşılığına geçişten sonra değil önce karar vermelisin. Multisite, Polylang ya da WPML çevirileri farklı modellerle ele alır ve Sanity’nin locale yapısını seçtiğin yaklaşıma bölen transform hiç de basit değildir. Bunu beş dilli bir multisite’ta koştum ve sana şunu söyleyebilirim: çok dillilik bir çeviri problemi değil, bir mimari problemidir. Önce mimariye karar ver. Almanca uzar, Türkçe daha da uzar, Arapça ters yöne akar — hedef modelin bir dili varsayıyorsa, çoktan başarısız oldun.


Dürüst kapanışım

Sanity’den WordPress’e geçmek, sofistikasyon merdiveninde bir basamak aşağı inmek değildir. Tek kanallı bir sitede bu, doğru düzeltmedir — çok ekran için kurulmuş bir mimariyi, sıradan insanların izin istemeden yayın yapmasına imkân veren bir platformla takas etmek.

Ama modelleme işini yap. Kendi CMS’imin yirmi yıl önce çökmesinin sebebi kötü bir export rutini değildi. Sebebi, geçmişi doğru düzgün ileri taşımamış olmamdı — geriye dönük uyumluluğu olmayan bir sistem kurdum ve sonunda kendi kullanıcılarımı terk ettim, çünkü onları taşıyamadım. WordPress tam da bunu asla yapmadığı için ayakta kalıyor. Bu erdemi özensiz bir geçişle bozma.

Modeli eşle. İhtiyacın olmayanı buda. Her Portable Text tipini elle ele al. Referansları iki geçişte yap. Staging’de sıkıcılaşana kadar deneme koşusu yap. Yönlendirmelerini cutover’dan önce ayarla.

Bunu yap; içerik, sıradan insanların onu doğru ve yaşar tutabileceği bir yere iner — ki bu da, dinleyen herkese söyleyip durduğum gibi, işin ta kendisidir.


Son Bir Şey: “Peki Sanity’nin Yaptığını WordPress’le Yapamaz mısın?”

Biri geçmeye karar verir vermez sorduğu ilk soru şu oluyor: Sanity’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 Sanity’ye para verme sebebin — yapılandırılmış içeriğin, isteyen her arayüze JSON olarak dağıtılması — WordPress bunu yıllardır, hem de göz önünde yapıyor. Headless tartışmasını kaybetmedi; yuttu, içine aldı.

Demek ki Sanity’den çıkışın tek değil, iki dürüst yolu var:

  • Klasik WordPress — bu yazının geri kalanı. Editörlere temalarını geri 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 Vercel’de.

İçeriğini custom post types ve ACF (veya native bloklar) ile modelle, WPGraphQL ile sorgula; arayüzün altındaki CMS’in değiştiğini pek fark etmez bile. Headless’in her avantajı sende kalır. Asıl seni dik oturtacak kısım da şu: üstüne, saf bir headless SaaS’ın sana asla vermediği şeyleri kazanırsın.

  • Gerçek bir ticaret motoru. WooCommerce. Headless-only bir 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 ekosistemi; 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 Sanity düpedüz yapmıyor — ticaret, eklenti ekonomisi, sayaçsız self-host. Sanity işini iyi yapıyor; 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. Headless katmanını ekle, WordPress’in zaten iyi yaptığı her şeyi yanında tut; aşağıya değil, arkanda çok daha büyük bir alet çantasıyla istediğin modele geçmiş olursun.

İşte sürpriz bu. Headless ile WordPress arasında seçim yapmana gerek yoktu. İkisi birden senin olabilir.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Close Search Window