Next.js SEO Checklist: Proje Başlangıç Kontrol Listesi

Next.js SEO Checklist: Proje Başlangıç Kontrol Listesi
Next.js, SEO dostu web uygulamaları geliştirmek için mükemmel bir framework'tür. Sunucu tarafı rendering, statik site oluşturma ve dahili optimizasyon araçları sayesinde arama motorlarında üst sıralara çıkmanızı kolaylaştırır. Bu rehberde yeni bir Next.js projesi başlatırken uygulamanız gereken SEO kontrol listesini adım adım ele alacağız.
1. Metadata ve Head Yapılandırması
App Router ile Metadata
// app/layout.js — Global metadata
export const metadata = {
metadataBase: new URL('https://www.example.com'),
title: {
default: 'Site Adı — Ana Açıklama',
template: '%s | Site Adı',
},
description: 'Sitenizin genel açıklaması. 150-160 karakter ideal.',
keywords: ['anahtar kelime 1', 'anahtar kelime 2'],
authors: [{ name: 'Yazar Adı' }],
creator: 'Yazar Adı',
publisher: 'Site Adı',
robots: {
index: true,
follow: true,
googleBot: {
index: true,
follow: true,
'max-video-preview': -1,
'max-image-preview': 'large',
'max-snippet': -1,
},
},
openGraph: {
type: 'website',
locale: 'tr_TR',
url: 'https://www.example.com',
siteName: 'Site Adı',
title: 'Site Adı — Ana Açıklama',
description: 'Open Graph açıklaması',
images: [
{
url: '/og-default.jpg',
width: 1200,
height: 630,
alt: 'Site Adı',
},
],
},
twitter: {
card: 'summary_large_image',
site: '@twitterHandle',
creator: '@twitterHandle',
},
alternates: {
canonical: 'https://www.example.com',
languages: {
'tr-TR': 'https://www.example.com',
'en-US': 'https://en.example.com',
},
},
verification: {
google: 'google-verification-code',
yandex: 'yandex-verification-code',
},
};
Sayfa Bazlı Metadata
// app/blog/[slug]/page.js
export async function generateMetadata({ params }) {
const post = await getPost(params.slug);
return {
title: post.title,
description: post.excerpt,
openGraph: {
title: post.title,
description: post.excerpt,
type: 'article',
publishedTime: post.publishedAt,
modifiedTime: post.updatedAt,
authors: [post.author.name],
images: [{ url: post.coverImage, width: 1200, height: 630 }],
},
alternates: {
canonical: `/blog/${params.slug}`,
},
};
}
2. Sitemap ve Robots.txt
// app/sitemap.js — Dinamik sitemap
export default async function sitemap() {
const posts = await getAllPosts();
const pages = await getAllPages();
const postUrls = posts.map(post => ({
url: `https://www.example.com/blog/${post.slug}`,
lastModified: new Date(post.updatedAt),
changeFrequency: 'weekly',
priority: 0.8,
}));
const pageUrls = pages.map(page => ({
url: `https://www.example.com/${page.slug}`,
lastModified: new Date(page.updatedAt),
changeFrequency: 'monthly',
priority: 0.6,
}));
return [
{
url: 'https://www.example.com',
lastModified: new Date(),
changeFrequency: 'daily',
priority: 1.0,
},
...postUrls,
...pageUrls,
];
}
// app/robots.js — Dinamik robots.txt
export default function robots() {
return {
rules: [
{
userAgent: '*',
allow: '/',
disallow: ['/api/', '/admin/', '/private/'],
},
],
sitemap: 'https://www.example.com/sitemap.xml',
};
}
3. Structured Data (JSON-LD)
// components/JsonLd.js
export default function JsonLd({ data }) {
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(data) }}
/>
);
}
// app/page.js — Organization schema
import JsonLd from '@/components/JsonLd';
export default function Home() {
const organizationSchema = {
'@context': 'https://schema.org',
'@type': 'Organization',
name: 'Site Adı',
url: 'https://www.example.com',
logo: 'https://www.example.com/logo.png',
sameAs: [
'https://twitter.com/handle',
'https://github.com/handle',
'https://linkedin.com/in/handle',
],
};
return (
<>
<JsonLd data={organizationSchema} />
{/* Sayfa içeriği */}
</>
);
}
// app/blog/[slug]/page.js — Article schema
const articleSchema = {
'@context': 'https://schema.org',
'@type': 'Article',
headline: post.title,
description: post.excerpt,
image: post.coverImage,
datePublished: post.publishedAt,
dateModified: post.updatedAt,
author: {
'@type': 'Person',
name: post.author.name,
url: post.author.url,
},
publisher: {
'@type': 'Organization',
name: 'Site Adı',
logo: { '@type': 'ImageObject', url: 'https://www.example.com/logo.png' },
},
};
4. Resim Optimizasyonu
// Next.js Image component
import Image from 'next/image';
// Otomatik optimizasyon, lazy loading, responsive
<Image
src="/hero.jpg"
alt="Açıklayıcı alt text — SEO için kritik"
width={1200}
height={630}
priority // LCP resminde kullanın
quality={85}
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 1200px"
placeholder="blur"
blurDataURL="data:image/jpeg;base64,..."
/>
// next.config.js — Image yapılandırması
/** @type {import('next').NextConfig} */
module.exports = {
images: {
formats: ['image/avif', 'image/webp'],
remotePatterns: [
{ protocol: 'https', hostname: 'cdn.example.com' },
],
deviceSizes: [640, 750, 828, 1080, 1200, 1920],
imageSizes: [16, 32, 48, 64, 96, 128, 256],
},
};
5. URL Yapısı ve Yönlendirmeler
// next.config.js — Redirects ve rewrites
module.exports = {
async redirects() {
return [
// www yönlendirmesi (Vercel'de otomatik)
{
source: '/:path*',
has: [{ type: 'host', value: 'example.com' }],
destination: 'https://www.example.com/:path*',
permanent: true, // 301
},
// Eski URL'lerden yeni URL'lere
{
source: '/blog/old-post-url',
destination: '/blog/new-post-url',
permanent: true,
},
// Trailing slash tutarlılığı
{
source: '/blog/:slug/',
destination: '/blog/:slug',
permanent: true,
},
];
},
// trailing slash yapılandırması
trailingSlash: false,
};
6. Performans Optimizasyonları
// app/layout.js — Font optimizasyonu
import { Inter } from 'next/font/google';
const inter = Inter({
subsets: ['latin', 'latin-ext'],
display: 'swap',
preload: true,
});
export default function RootLayout({ children }) {
return (
<html lang="tr" className={inter.className}>
<body>{children}</body>
</html>
);
}
// Statik sayfalar için ISR
export const revalidate = 3600; // 1 saat
// Route segment config
export const dynamic = 'force-static'; // veya 'force-dynamic'
// Loading UI — UX ve Core Web Vitals
// app/blog/loading.js
export default function Loading() {
return <div className="animate-pulse">Yükleniyor...</div>;
}
7. Erişilebilirlik (a11y) ve SEO
<!-- Semantik HTML kullanımı -->
<header>
<nav aria-label="Ana navigasyon">
<ul>
<li><a href="/">Ana Sayfa</a></li>
<li><a href="/blog">Blog</a></li>
</ul>
</nav>
</header>
<main>
<article>
<h1>Tek bir h1 — sayfa başlığı</h1>
<p>İçerik...</p>
</article>
</main>
<footer>
<nav aria-label="Footer navigasyon">...</nav>
</footer>
<h1> kullanın. Heading hiyerarşisini (h1 > h2 > h3) doğru sıralayın. Bu hem erişilebilirlik hem de SEO için kritiktir.
8. SEO Kontrol Listesi Özeti
- Metadata: Her sayfada benzersiz title ve description
- Canonical URL: Her sayfada canonical tag
- Sitemap: Dinamik sitemap.xml
- Robots.txt: Doğru yapılandırma
- Structured Data: JSON-LD schema markup
- Open Graph: Sosyal medya kartları
- Resim Optimizasyonu: Alt text, format, boyut
- Core Web Vitals: LCP, INP, CLS hedefleri
- HTTPS: Güvenli bağlantı
- Mobil Uyumluluk: Responsive tasarım
- URL Yapısı: Temiz, açıklayıcı URL'ler
- Heading Hiyerarşisi: Tek h1, doğru sıralama
- İç Linkleme: Anlamlı anchor text'ler
- 404 Sayfası: Özel not-found sayfası
- Yönlendirmeler: 301 redirect'ler
noindex meta tag'ını production'a deploy etmeden önce kaldırdığınızdan emin olun. Staging ortamlarında kullanılan robots: noindex production'da büyük SEO hasarına yol açar.
Sonuç
Next.js, SEO dostu uygulamalar geliştirmek için kapsamlı araçlar sunar. Metadata API ile dinamik meta tag'lar, sitemap ve robots.txt oluşturma, Image component ile resim optimizasyonu ve ISR ile güncel içerik sunma bu araçların başlıcalarıdır. Bu kontrol listesini projenizin başlangıcında uygulayarak SEO temellerini sağlam bir şekilde atabilirsiniz. Düzenli olarak Google Search Console ve PageSpeed Insights ile metriklerinizi izleyin.