~/zafer
Tüm yazılara dön
5 dk okuma

Next.js SEO rehberi: Metadata, sitemap ve JSON-LD ile teknik SEO

Next.js SEO rehberi: Metadata, sitemap ve JSON-LD ile teknik SEO

Teknik SEO, bir sayfaya anahtar kelime eklemekten çok daha fazlasıdır. Arama motorunun sayfanın ne hakkında olduğunu, hangi URL'nin asıl sürüm olduğunu ve içeriğin ne zaman yayımlandığını kolayca anlamasını sağlamaktır. Next.js App Router bu iş için güçlü araçlar sunuyor; fakat doğru yapı kurulmadığında dinamik blog yazıları, canonical URL'ler ve sosyal medya önizlemeleri hızla tutarsızlaşabilir.

Bu yazıda Next.js ile geliştirdiğim bir blogda kullandığım temel teknik SEO katmanlarını anlatıyorum: metadata, canonical URL, Open Graph, sitemap, robots ve BlogPosting JSON-LD.

1. Her sayfanın tek, anlamlı bir arama niyeti olsun

SEO'nun başlangıç noktası teknik ayar değil, sayfanın cevabıdır. Örneğin bu sayfanın hedefi “Next.js SEO nasıl yapılır?” sorusuna uygulamaya dönük bir yanıt vermek. Başlık, ilk paragraf ve alt başlıklar bunu destekliyor. Bir sayfayı aynı anda “Next.js eğitimi”, “en iyi React framework” ve “web tasarım ajansı” için sıralamaya çalışmak yerine, tek niyete odaklanmak daha anlaşılır bir içerik üretir.

Başlıkta ana sorguyu doğal biçimde kullanın; özet alanında okuyucunun ne kazanacağını söyleyin. Bu sitedeki her yazının titleTr ve excerptTr alanları, sayfa başlığı ile meta açıklamasının temelini oluşturuyor.

2. Metadata'yı içerikle birlikte üretin

Statik sayfalarda metadata export'u yeterlidir. Blog gibi slug ile çalışan dinamik sayfalarda ise yazı kaydını çekip generateMetadata ile metadata üretmek daha güvenlidir. Böylece sayfa başlığı, açıklama, Open Graph görseli ve canonical URL tek içerik kaynağından gelir.

export async function generateMetadata({ params }: Props): Promise<Metadata> {
  const post = await getPost((await params).slug);

  return {
    title: post.titleTr,
    description: post.excerptTr ?? undefined,
    alternates: { canonical: `/post/${post.slug}` },
    openGraph: {
      type: "article",
      title: post.titleTr,
      description: post.excerptTr ?? undefined,
      publishedTime: post.createdAt.toISOString(),
    },
  };
}

Next.js, URL tabanlı metadata alanları için kök layout'ta metadataBase tanımlamanızı bekler. Bu değeri gerçek alan adınızla ayarlayın. Özellikle production build sırasında kullanılan APP_URL yanlışsa canonical ve paylaşım URL'leri de yanlış üretilir.

3. Canonical URL ile kopya sayfa sinyalini azaltın

Bir içerik /post/nextjs-seo-rehberi-metadata-sitemap-json-ld adresinde yaşıyorsa, canonical URL de aynı adresi göstermelidir. Query string'ler, farklı hostlar veya yanlış yönlendirmeler aynı içeriğin birden fazla sürümünü oluşturabilir. alternates.canonical her yazıda açıkça ayarlandığında, arama motoruna tercih edilen adresi bildirirsiniz.

Canonical etiketi tek başına sıralama garantisi değildir. Yine de HTTPS, tutarlı yönlendirmeler, tek alan adı ve doğru internal link'lerle birlikte temel bir hijyen adımıdır.

4. Sosyal paylaşım için Open Graph görselini ihmal etmeyin

Arama sonucu dışında, yazınız çoğu zaman LinkedIn, X veya bir mesajlaşma uygulamasında ilk kez görülür. Open Graph başlığı, açıklaması ve görseli, paylaşım kartını belirler. Her yazı için kapak görseli kullanabiliyorsanız coverImage değerini doğru, mutlak bir URL ile saklayın. Görsel yoksa tutarlı bir dinamik OG görseli üreten route iyi bir yedektir.

Open Graph verisini metinden bağımsız uydurmak yerine yazı kaydından üretmek önemlidir. Sonradan başlığı değiştirirseniz paylaşım kartı da aynı içerikle güncellenir.

5. Sitemap statik bir dosya olmak zorunda değil

Blog yayınlandıkça sitemap'in manuel unutulması çok yaygın bir hata. Next.js'in sitemap.ts metadata route'u bu işi kodla çözer. Bu projede önce sabit rotalar, sonra API'den gelen yayımlanmış yazı ve proje rotaları birleştiriliyor:

const [posts, projects] = await Promise.all([
  fetchJson(`${API_ORIGIN}/api/posts?page=1&pageSize=100`),
  fetchJson(`${API_ORIGIN}/api/projects?page=1&pageSize=100`),
]);

return [
  { url: `${APP_URL}/posts`, changeFrequency: "weekly", priority: 0.8 },
  ...posts.items.map((post) => ({
    url: `${APP_URL}/post/${post.slug}`,
    lastModified: post.updatedAt,
  })),
];

Burada kritik nokta yalnızca published içerikleri dönen herkese açık endpoint'i kullanmaktır. Taslakları sitemap'e koymak, arama motoruna erişemeyeceği URL'leri duyurmak demektir. Yeni yazı yayımlandığında sitemap otomatik güncellenir.

6. JSON-LD ile içeriğin türünü açıkça anlatın

Arama motorları HTML'i okuyabilir; fakat yapılandırılmış veri içeriğin türünü daha açık ifade eder. Blog yazılarında BlogPosting şeması; başlık, açıklama, yayın tarihi, güncelleme tarihi, görsel, yazar ve ana sayfa ilişkisini taşır.

<script
  type="application/ld+json"
  dangerouslySetInnerHTML={{
    __html: JSON.stringify({
      "@context": "https://schema.org",
      "@type": "BlogPosting",
      headline: post.titleTr,
      description: post.excerptTr,
      datePublished: post.createdAt.toISOString(),
      dateModified: post.updatedAt.toISOString(),
      author: { "@type": "Person", name: "Zafer Hüzmeli" },
    }),
  }}
/>

JSON-LD eklemek zengin sonuç sözü vermez; ancak sayfanın anlamını makinenin daha güvenilir biçimde çözmesine yardım eder. Değerler ekranda görünen içerikle aynı olmalıdır.

7. İç bağlantıları konu kümeleriyle kurun

Bir yazı yalnız başına güçlü değildir. Bu SEO rehberinden, monorepo ve Docker yazısına bağlanmak mantıklıdır; çünkü Next.js metadata ayarlarının doğru çalışması production build sürecine bağlıdır. Aynı şekilde Docker yazısından buraya dönmek, okuyucuya yayına çıkış ile görünürlük arasındaki ilişkiyi gösterir.

İç bağlantıda “buraya tıklayın” yerine hedefi anlatan bağlantı metni kullanın. Örneğin Turborepo ve Docker ile üretime hazır bir monorepo kurmak bağlantısı hem kullanıcıya hem arama motoruna hedef sayfayı açıkça anlatır.

Yayın öncesi kısa kontrol listesi

  • Başlık, açıklama ve H1 aynı arama niyetini destekliyor mu?
  • Canonical URL gerçek HTTPS alan adına mı gidiyor?
  • Open Graph başlığı/açıklaması ve görseli mevcut mu?
  • Yazı yayımlandıktan sonra sitemap'te görünüyor mu?
  • JSON-LD'deki tarih, yazar ve başlık görünür içerikle tutarlı mı?
  • İlgili en az iki yazıya doğal internal link var mı?

Teknik SEO, iyi bir içeriğin yerine geçmez. Fakat iyi içeriğin taranmasını, doğru URL ile indekslenmesini ve paylaşılır görünmesini sağlar. Next.js'in Metadata API'sini içerik modelinizle birleştirdiğinizde bu iş, her yazıda elle tekrar edilen bir görev olmaktan çıkar.