Yaklaşık bir yıl önce, üç seçenekle çalışmaya başladığımda bir CMS geliştirmeye karar verdim ve hiçbiri ihtiyaçlarımı karşılamıyordu:
- WordPress — çalışıyor, ancak haftada 250’den fazla eklenti güvenlik açığı (Patchstack 2024). Her hafta siteleri güncelliyorum. Artık bıktım.
- Contentful / Sanity — modern, ama KOBİ kullanımları için aylık 300 $ giriş ücreti. Tedarikçi bağımlılığı gerçek.
- Strapi / Payload — sağlam, ancak yalnızca Node.js. Ben bir PHP/Laravel ekibiyim.
Bu nedenle, UnfoldCMS’i geliştirdim — tek bir ürün olarak sunulan kendi kendine barındırılan bir Laravel CMS, bir çerçeve değil, bir yapı. Bu yazı, içerik açısından nelerin bulunduğuna dair bir tur olacaktır. Pazarlama versiyonu değil — “işte 183 yönetici sayfası” versiyonu.
2026’da bir CMS seçiyorsanız, bu tür bir ayrıntılı inceleme umarım satıcılar tarafından yayınlanır.
Yığın, kısaca
Yığın, kısaca
- Laravel 11 + Inertia 2 + React 19 + TypeScript
- Tailwind v4 + shadcn/ui (50+ bileşen)
- MySQL / MariaDB
- Spatie Media Library, Spatie Permission (RBAC), Spatie Activity Log
- ~80MB RAM ile aylık 5$’lık Hetzner VPS’te çalıştırılıyor
Shadcn + Tailwind teması üzerinde daha önce yazdım. Bu yazı, CMS yüzeyine — modüller, editör, yayınlama hattına odaklanacak.
Kutunun içinde neler var
Kutunun içinde neler var
Buradaki her modül yerleşiktir. “Eklenti pazar yeri” yok — Laravel hizmet sağlayıcılarına sahiptir, bu da genişletme modelidir.
Gönderiler ve Sayfalar
Gönderiler ve Sayfalar
Temel yayıncılık ilkeleri. Her ikisi de aynı modeli paylaşır (Post ve content_type enum), ancak farklı şekilde görüntülenir.
- Gönderiler = blog girişleri,
/blog/{slug}altında indekslenir, blog dizininde listelenir. - Sayfalar = kök düzeyindeki içerikler,
/about,/pricing,/migrate-from-wordpressgibi. - Aynı editör, aynı medya yönetimi, aynı SEO alanları. Tek fark URL yönlendirmesidir.
Editor, Tiptap’ın temeli üzerinde inşa edilmiş yapılandırılmış bir blok editörüdür. Her blok, başlık, paragraf, resim, kod bloğu, çağrı, tablo gibi ayrı alanlardır — serbest formatlı bir blob değildir. Editörler öngörülebilir düzenlere sahip; geliştiriciler temiz veriler alır.
Planlı yayınlama yerleşik olarak bulunmaktadır. posted_at gelecekte + is_published = true = gönderi planlanan zamanda görüntülenir. Tek bir Laravel zamanlayıcı girişi her dakika çalışır ve görünürlük durumunu değiştirir.
Medya Kütüphanesi
Medya Kütüphanesi
Alt yapıda Spatie Media Library var. Kullanmayı değerli kılan üç şey vardır:
- Polimorfik ilişkiler — her model medya içerebilir (gönderiler, kullanıcılar, ayarlar, özel modeller).
- Taleple dönüştürmeler —
large,medium,thumbnailbir kez tanımlayın; dönüşümler ilk talep edildiğinde oluşturulur. - Öne çıkan resim koleksiyonları — her gönderi için ayrılmış
featured-imagekoleksiyonu, gövde içindeki resimlerden ayrı.
Uyarı: kalıtım olarak image_large metin sütunu göz alıcı görünüyor, ancak “hero resmini ayarla” için cazip. Yapmayın. Spatie koleksiyonlarını kullanın — şablon, uygun oranların işlenmesiyle otomatik olarak görüntüler.
Menüler
Menüler
Ağaç tabanlı menü oluşturucusu. Sürükle-bırak sıralama. Her menü öğesi, iç yollar (Laravel’in adlandırılmış yolları aracılığıyla çözülür), dış URL’ler veya içerik (slug’dan URL otomatik olarak oluşturulur) ile bağlantılıdır.
Her site için birden fazla menü — Üstbilgi, Altbilgi, Mobil, Kenar Çubuğu — ve iç içe çocukları destekler. Ön uç şablonlar menüleri slug ile alır:
$mainMenu = Menu::bySlug('main');
Formlar
Formlar
JSON şeması ile bir form oluşturucu. Alanlar, doğrulama kuralları, başarı/hata mesajları, yönlendirme hedefleri — hepsi yönetim panelinden yapılandırılabilir. Gönderimler form_submissions tablosuna gider; yöneticiler filtrelerle bir liste görebilir, CSV olarak dışa aktarabilir veya e-posta ya da webhook’lara iletebilir.
Mimari seçimi: formlar CMS’in bir özelliğidir, ayrı bir uygulama değildir. Kimlik doğrulama, oran sınırlamaları, spam filtreleme (Spatie honeypot) ve aktivite günlüğü ile sistemi paylaşır.
Ayarlar
Ayarlar
Konfigürasyona dayalı bir anahtar-değer deposu. Şema, config/site.php içinde yer alır — varsayılanlar bir kez ayarlanır, yönetici UI şemadan oluşturulur, ön uç Setting::get('key', $fallback) ile okur.
Bu neden önemlidir: bir müşteri “duyuru banner’ı göster” anahtarı isterse, bir migration, form, denetleyici ve Blade değişkeni yazmanız gerekmez. Şemaya bir anahtar eklemeniz yeterli ve otomatik olarak yönetici panelinde görünür hale gelir.
Temalar
Temalar
Üç tema ile birlikte gelir — Varsayılan (mavi), Mor, Unfold (soft mor). Geçiş yapmak bir CSS değişkeni değişikliğiyle mümkündür (önceki yazıda detaylandırılmıştır). Temanın temeli data-theme="..." kök öğesindeki + Tailwind v4’ün @theme direktifi ile yapılır.
Tasarımlar açısından kapsam: renkler, kenar, font yelpazesi. Kapsam dışında olan: düzen, boşluk, bileşen şekli. Bu kasten yapılmıştır — temalar görseldir, yapısal değildir.
Şablonlar
Şablonlar
Temalar üzerinde şablonlar — CMS ile birlikte gelen tam ön uç tasarımları. Bu sitedeki aktif olan “Aurora” olup, kendi örnek verileri, blade şablonları ve bölüm bileşenleri vardır. Şablonlar kurulum sırasında değiştirilir; çalışma zamanında değişim yapmak daha zordur çünkü her biri kendi ana sayfa bölüm verisiyle birlikte gelir.
SEO
SEO
ralphjsmit/laravel-seo paketine dayalı olarak, site genelindeki varsayılanlarla ve gönderi başına değişikliklerle genişletilmiştir.
Otomatik olarak oluşturulanlar:
-
ve meta açıklaması (belirli geçersiz kılma alanları ile) - Açık Grafik + Twitter kart etiketleri
- JSON-LD şemasında:
Article,BreadcrumbList,Organization - Doğru son eğik çizgi işleme ile kanonik URL’ler
hreflangetiketleri çok dilli siteler için
CMS için SEO başlığı varsayılan olarak gönderi başlığıdır — ancak başlık, uygun isimleri bozan bir şekilde büyük/küçük harf yapılır (“WordPress” → “WordPress”). Zor yoldan öğrendim: her zaman seo_title ve meta_desc‘yi açıkça ayarlayın, varsayılan ayara güvenmeyin. Bu, içerik yayınlama becerimizde şimdi bir kural haline geldi.
RBAC
RBAC
Spatie Permission. Üç varsayılan rol ile birlikte gelir — Süper Yönetici, Editör, Yazar — ve yönetim panelinden daha fazlasını ekleyebilirsiniz. İzinler ayrıntılıdır (model başına + eylem başına), yalnızca rol tabanlı değildir.
Middleware durumu doğrudan Laravel ile ilgili:
Route::middleware(['auth', 'role:editor|admin'])->group(function () {
Route::resource('posts', PostController::class);
});
Hiçbir satıcı büyüsü yok. Eğer Spatie Permission kullandıysanız, tam olarak ne olduğunu biliyorsunuz.
Çok Dilli
Çok Dilli
spatie/laravel-translatable. Her çevirilebilir alan (title, body, seo_title, meta_desc) bir JSON haritası olarak {locale: value} şeklinde saklanır. Yönetim panelinde bir yerel dil değiştirici gösterilir; ön yüz, URL öneki (/fr/about) veya alan adı üzerinden çözümler üretir.
Henüz mevcut olmayan: otomatik çeviri (makine çevirisi süreci). Editörler şu anda manüel olarak çeviri yapmaktadır.
Yayınlama Hattı (en uzun süren kısım)
Yayınlama Hattı (en uzun süren kısım)
“Gönderiyi kaydet” düğmesi yapmak bir hafta sonu alır. Taslakları, planlı yayınlamayı, site haritası yenilemeyi, ön belleği geçersiz kılmayı, ve SEO güncellemelerini koşul yarışı olmaksızın ele alan bir yayınlama hattı oluşturmanın bir yılı aldı.
Bir yayım eyleminin arkasında olanlar:
- Doğrulama — gerekli alanlar, slug benzersizliği, meta açıklama uzunluğu
- Markdown → HTML dönüşümü (sunucu tarafında; gövde HTML olarak saklanır, böylece şablon sadece ham olarak render eder)
- SEO kayıt senkronizasyonu —
seo_title,meta_desc,og_imageile ilgili bir tabloya yazılır - Spatie medya ekleme — öne çıkan resim, geçici yüklemeden kalıcı koleksiyona geçirilir
- Site haritası yenileme —
php artisan sitemap:generatesenkron bir şekilde çalışır (paylaşımlı barındırma için kuyruk işleyici gerekmez) - Ön bellek geçersiz kılma —
view:clear,route:clear, yapılandırılmışsa kenar ön bakım temizleme - Aktivite günlüğü — Spatie ActivityLog, kimin neyi yayımladığını kaydeder
Yukarıdakilerin tümü, CMS paylaşımlı barındırma hedeflediğinden, istekte senkron bir şekilde çalışır, bu nedenle kuyruk işleyicileri her zaman mevcut değildir. Gerçek bir VPS’de iseniz, QUEUE_CONNECTION=database‘yu değiştirebilir ve otomatik olarak kuyruklar. Senkron yedekleme, “5$’lık bir VPS’ye dağıtım yapma” olmasını sağlar.
Dağıtım Hikayesi
Dağıtım Hikayesi
Tek bir artisan komutu: php artisan deploy. Bu işlem yapılır:
- Dağıtım dalında temiz çalışma ağacını doğrular
- git’e gönderir
- Sunucuya çeker
composer install --no-devçalıştırır (değişmediği takdirdecomposer.lockatlanır)php artisan migrate --forceçalıştırır- Ön yüz varlıklarını
pnpm run buildile yerel olarak oluşturur, sunucuya rsync ile senkronize eder (JS/CSS değişmediği takdirde atlanır) - config/view/route ön belleğini temizler
- HTTP 200’ü doğrular
Bu komutta gömülü olan dersler:
- Ön yüz, yerel olarak oluşturulur, sunucuda değil. Daha hızlıdır ve sunucuda Node gerektirmeden kaçınır.
- Değişiklik olmadığında Composer atlama, dağıtım başına ~30 saniye tasarruf sağlar.
- Rsync üzerinden SCP varlıklar için — artımlı, yalnızca değişen dosyaları yükler.
- En sonunda HTTP 200 doğrulaması, sessizce bozulmuş dağıtımları yakalar.
Artık birçok Laravel uygulaması dağıttığım için, bu dağıtım komutunu bir projenin değil, ürünün bir parçası olarak düşünüyorum.
Henüz kutuda olmayanlar
Henüz kutuda olmayanlar
Samimi bir liste:
Kamuya Açık Headless API
Kamuya Açık Headless API
İç REST çalışıyor. Kamu uç noktaları + imzalı webhook’lar 2026’nın sonlarında gelmektedir. O zamana kadar UnfoldCMS’i bir Next.js sitesi için içerik arka uç olarak kullanmak istiyorsanız, JSON döndüren ince bir Laravel yönlendirmesi yazmalısınız:
Route::get('/api/blog/{slug}', function (string $slug) {
return Post::published()->whereSlug($slug)->firstOrFail();
});
Üç satır, ama anlıyorum — bu, cilalı bir kamu API’si ile aynı şey değil. 2026’nın sonlarına doğru.
Eklenti pazar yeri
Eklenti pazar yeri
Bunu inşa etmiyorum. Genişletme modeli Laravel hizmet sağlayıcıları + middleware ile. Laravel’i biliyorsanız, onu nasıl genişleteceğinizi biliyorsunuz. Bilmiyorsanız, öğrenme eğrisi “Laravel’in kendisi”dir ve bu gerçek bir maliyet, aynı zamanda aktarılabilir bir maliyettir.
Görsel Sayfa Oluşturucu
Görsel Sayfa Oluşturucu
Blok editörü yapılandırılmış içeriği iyi bir şekilde yönetiyor. Webflow tarzı sürükle-bırak oluşturucusu olmayacak ve muhtemelen olmayacak — farklı bir kategori. Eğer onu istiyorsanız, Webflow veya Storyblok doğru araçtır.
Çoklu site / çok kiracılı
Çoklu site / çok kiracılı
Bugün her kurulum için tek bir site. 20 müşteri sitesi yöneten ajanslar, 20 kurulum yapacak (Hetzner’de ucuz — 5$ x 20 = 100$/ay barındırma; lisans da her site başına).
Rakamlar
Rakamlar
Somut, özlem değil:
- Kod satırı sayısı: ~80K (PHP) + ~45K (TS/TSX) — gerçek bir ürün, oyuncak değil
- Yönetim panelindeki sayfalar: 183
- shadcn bileşenleri: 50+
- Gelen temalar: 3
- Hafıza ayak izi: ~80MB etkin Hetzner CX22 üzerinde
- Soğuk başlangıç: ~250ms ilk istek, ~40ms sonra sıcak
- Derleme süresi: ~12 saniye (Vite + Inertia paketi)
- Testler: ~600 PHPUnit testi, kritik yollar üzerinde ~80% kapsama
Fiyatlandırma Kararı
Fiyatlandırma Kararı
Site başına tek seferlik lisans. 99 $ Solo, 199 $ Pro, 499 $ Ajans.
Akıl yürütme: abonelikler müşterilerin verilerini esir alır. Tek seferlik bir lisans, bir müşterinin bunu kurup bir daha hiç ücret ödemeden, yüklemeyi yüklenecek olmasıdır — kod, veritabanı, içerik. Eğer yarın kaybolursam, kurulum çalışmaya devam eder.
Olumsuz: ART değeri daha zor tahmin edilir. Pozitif: müşteriler bana gerçekten güveniyor. İki yıl sonra, bu modeli tekrar seçeceğim.
Neden inşa ettim (kısa versiyon)
Neden inşa ettim (kısa versiyon)
WordPress bazı siteler için işe yarar. Contentful işletme ekipleri içindir. Hiçbiri ara aşamadaki KOBİ’ler için 5-20 site çalıştıran küçük ajanslar için uygun değildir. Müşteriler verilerini sahiplenmek, akılcı bir deneyim istemekte ve büyüdükçe aylık fatura olmadan CMS’e ihtiyaç duymaktadır.
UnfoldCMS, bu boşluk için inşa ettiğim bir üründür. Herkes için doğru cevap değil — karşılaştırma sayfaları kimin için uygun olduğunu ve kimin için olmadığını açıkça belirtmektedir.
Deneyin
Deneyin
Samimi eleştiriler yorumlarda kabul edilir — bu, ürünün daha iyiye gitmesini sağlar.
— Hamed
Kaynak: Orijinal Makale


