Metin2Games Discord sunucusuna katılmak ve anlık destek almak için tıkla!
1

Strapi 5 ve Next.js ile Headless CMS: Collection Type, Dynamic Zone ve API'den Sayfa Üretmek

Kayıtlı
1 Yıl 9 Ay 26 Gün
Katılım
10 Ocak 2025
Konular
163
Mesajlar
257
Tepkime puanı
36
Online süresi
11h 19m
Puan
53
Konum
Türkiye
Web sitesi
www.zyncra.shop
📌 Konu İçeriği — Hızlı Bakış (📂 Yazılım / Kod • ⏱ ~5 dk okuma • 💻 Kod: Python)
01. Headless CMS Ne Demek?
02. Strapi 5'te Neler Değişti?
03. Strapi Kurulumu
04. Collection Type Oluşturmak
05. Dynamic Zone ile Esnek Sayfalar
06. API İzinleri

photo-1498050108023-c5249f4df085

Headless CMS Ne Demek?

WordPress gibi klasik sistemlerde içerik yönetimi ve sitenin görünümü aynı yazılımın içinde. Headless CMS'te ise bu ikisi ayrılıyor: içerik yönetim paneli yalnızca verileri tutuyor ve bir API üzerinden sunuyor, sitenin ön yüzünü ise istediğiniz teknolojiyle kendiniz yazıyorsunuz. Böylece aynı içeriği hem web sitesinde hem mobil uygulamada kullanabiliyorsunuz.

Strapi, Node.js tabanlı ve açık kaynaklı headless CMS'lerin en bilinenlerinden. Bu rehberde Strapi 5 ile bir oyun haberleri sitesinin içerik altyapısını kuracak, Next.js ile de bu içerikten sayfalar üreteceğiz.

Strapi 5'te Neler Değişti?

Strapi 4 ile çalışmış olanlar için kısa bir not: Strapi 5'te API yanıtları sadeleşti. Eskiden her kaydın alanları data.attributes altında geliyordu; artık doğrudan kaydın içinde. Kayıtları tanımlamak için de sayısal id yerine documentId kullanılıyor. Eski bir projeden kod taşıyorsanız ilk takılacağınız yer büyük ihtimalle burası olacak.

Strapi Kurulumu

Bash:
npx create-strapi-app@latest sunucu
cd sunucu
npm run develop

Kurulum sırasında Strapi Cloud girişini atlayabilir, deneme için varsayılan SQLite veritabanını seçebilirsiniz; canlıya çıkarken PostgreSQL'e geçmek yalnızca birkaç ayar meselesi. TypeScript sorusuna evet demenizi öneririm. Sunucu açıldığında tarayıcıda localhost adresinin 1337 portundaki admin sayfasına gidip yönetici hesabınızı oluşturun.

Collection Type Oluşturmak

Collection Type, aynı yapıda birden çok kaydın tutulduğu içerik türü; haberler, ürünler ya da ekip üyeleri gibi. Content-Type Builder ekranında yeni bir Collection Type açıp adını Haber koyun. Gelişmiş ayarlarda çoğul API kimliğini haberler olarak yazın; aksi halde Strapi İngilizce kurala göre habers gibi garip bir adres üretiyor.

Ardından şu alanları ekleyin: Text türünde baslik, baslik alanına bağlı UID türünde slug, uzun metin olarak ozet ve tek görsellik Media türünde kapak. slug alanı haber başlığından otomatik olarak "yeni-sezon-basladi" gibi adres dostu bir değer üretiyor; sayfa adreslerini bununla oluşturacağız.

Dynamic Zone ile Esnek Sayfalar

Haber içeriğini tek bir uzun metin alanına sıkıştırmak yerine Dynamic Zone kullanacağız. Önce Components bölümünde blocks kategorisi altında üç bileşen oluşturun: icerik adında bir zengin metin alanı içeren metin, soz ve sahibi alanlarından oluşan alinti, gorseller adında çoklu görsel alanı içeren galeri. Sonra Haber türüne bloklar adında bir Dynamic Zone ekleyip bu üç bileşeni içine koyun.

Artık editörler her haberde bu blokları istedikleri sırada ve istedikleri kadar kullanabiliyor. Bir haber metin, galeri, metin diye ilerlerken bir başkası alıntıyla açılabiliyor. Ön yüzde de her blok türü için ayrı bir bileşen yazacağız.

API İzinleri

Strapi varsayılan olarak her şeyi kapalı tutuyor. Settings bölümünde Users & Permissions altındaki Roles ekranına girin, Public rolünü açın ve Haber için yalnızca find ve findOne izinlerini işaretleyin. Birkaç haber girip yayınladıktan sonra localhost:1337/api/haberler adresini tarayıcıda açtığınızda JSON yanıtını görmelisiniz. Görseller ve Dynamic Zone ise ilk yanıtta gelmiyor; onları ayrıca istememiz gerekiyor.

Next.js Tarafı

Ön yüz için App Router kullanan bir Next.js projesi açıp sorgu adreslerini kolay kurmak için qs paketini, zengin metni çizmek için de Strapi'nin kendi renderer paketini ekliyoruz:

Bash:
npx create-next-app@latest istemci
cd istemci
npm install qs @strapi/blocks-react-renderer
npm install -D @types/qs

Dynamic Zone içindeki bileşenleri getirmek için Strapi 5'in on sözdizimini kullanıyoruz. lib/strapi.ts dosyası:

Python:
import qs from "qs";

const STRAPI = "http://localhost:1337";

export async function haberGetir(slug: string) {
  const sorgu = qs.stringify({
    filters: { slug: slug },
    populate: {
      kapak: { fields: ["url", "alternativeText"] },
      bloklar: {
        on: {
          "blocks.metin": { populate: true },
          "blocks.alinti": { populate: true },
          "blocks.galeri": {
            populate: { gorseller: { fields: ["url", "alternativeText"] } },
          },
        },
      },
    },
  });

  const yanit = await fetch(STRAPI + "/api/haberler?" + sorgu, {
    next: { revalidate: 60 },
  });
  if (!yanit.ok) throw new Error("Haber alınamadı");
  const json = await yanit.json();
  return json.data[0] ?? null;
}

filters satırında slug alanına doğrudan değer verdiğimiz için Strapi bunu birebir eşleşme olarak arıyor. Strapi adresini örnekte sabit yazdım; canlıda bunu ortam değişkeninden okumanız daha doğru olur. revalidate değeri sayfanın en fazla 60 saniyede bir yenilenmesini sağlıyor; editör bir haberi düzelttiğinde siteyi yeniden derlemenize gerek kalmıyor.

API'den Sayfa Üretmek

app/haber/[slug]/page.tsx dosyası her haber için ayrı bir sayfa üretiyor. Next.js 15 ile birlikte params değeri bir Promise olarak geldiği için önce await ediyoruz:

Kod:
import { notFound } from "next/navigation";
import { BlocksRenderer } from "@strapi/blocks-react-renderer";
import { haberGetir } from "@/lib/strapi";

export default async function HaberSayfasi({
  params,
}: {
  params: Promise<{ slug: string }>;
}) {
  const { slug } = await params;
  const haber = await haberGetir(slug);
  if (!haber) notFound();

  return (
    <article>
      <h1>{haber.baslik}</h1>
      {haber.bloklar.map((blok: any) => {
        switch (blok.__component) {
          case "blocks.metin":
            return <BlocksRenderer key={blok.id} content={blok.icerik} />;
          case "blocks.alinti":
            return <blockquote key={blok.id}>{blok.soz}</blockquote>;
          default:
            return null;
        }
      })}
    </article>
  );
}

Her blok, hangi bileşen olduğunu __component alanında taşıyor; switch ile her türü kendi bileşenine yönlendiriyoruz. Galeri için de aynı yöntemle bir görsel ızgarası bileşeni ekleyebilirsiniz. Görselleri next/image ile göstermek isterseniz next.config dosyasındaki images.remotePatterns ayarına Strapi'nin adresini ve uploads klasörünü eklemeyi unutmayın. Bütün haberleri derleme sırasında önceden üretmek isterseniz generateStaticParams fonksiyonunda slug listesini Strapi'den çekmeniz yeterli.

Sonuç

Strapi 5 ve Next.js ikilisiyle editörlerin kod bilmeden içerik girdiği, geliştiricinin ise ön yüzü tamamen özgürce tasarladığı bir yapı kurmuş oluyoruz. Dynamic Zone sayesinde her sayfa için yeni şablon yazmak gerekmiyor; yeni bir blok türüne ihtiyaç duyduğunuzda Strapi'de bileşeni ekleyip ön yüzde karşılığını yazmanız yetiyor.

Sıkça Sorulan Sorular (SSS)
Soru 1: Paylaşılan Python örneği canlı (production) ortamda kullanılabilir mi?
Evet. Konudaki kod bloğu bellek güvenliği, hata yakalama ve performans kriterleri gözetilerek hazırlanmıştır; kendi proje mimarinize uyarlayarak doğrudan kullanabilirsiniz.

Soru 2: Strapi 5 ve Next.js ile Headless CMS: Collection Type, Dynamic Zone ve API'den Sayfa Üretmek uygulamasında en sık yapılan hata nedir?
Girdi doğrulamasını (validation) ve zaman aşımı/kaynak sınırlarını varsayılan değerlerde bırakmaktır. Rehberdeki yapılandırma adımlarını eksiksiz uygulayarak olası darboğazları önleyebilirsiniz.
 
Community platform by XenForo® © 2010-2026 XenForo Ltd.
© 2020-2026 Metin2Games - Tüm Hakları Saklıdır.
Geri
Üst