
چکلیست سئوی Next.js (۲۰۲۵)
مقدمه
چکلیست عملی برای سئوی Next.js با متادیتا، OG/Twitter، canonical مطلق، robots/sitemap، JSON-LD، i18n و بهینهسازی Core Web Vitals.
قبل از شروع، بد نیست یادآوری کنیم که بهینهسازی موتور جستجو (SEO) بخش مهمی از هر پروژه وب است. با App Router و Metadata API مدیریت سئو سادهتر شده. در این مقاله یک چکلیست عملی و گامبهگام داریم تا پروژه Next.js شما در سال ۲۰۲۵ از نظر سئو کاملاً بهینه باشد.
نکته
این مقاله عملی و پروژهمحور است؛ کدها برای App Router در Next.js طراحی شدهاند.
فهرست
پیشنیازها
- Node.js 18+ برای سازگاری کامل با Next.js 14/15
- Next.js 14/15 (App Router)
- App Directory structure (مثل
app/layout.tsx,app/page.tsx) - دامنه واقعی و Google Search Console برای معرفی sitemap و پایش ایندکس/Core Web Vitals
راهنمای سریع
metadataBaseرا درapp/layout.tsxتنظیم کن.- OG/Twitter را با تصویر 1200×630 بهینه کن.
alternates.canonicalرا مطلق تنظیم کن.app/robots.tsوapp/sitemap.tsرا اضافه کن.- JSON-LD (Organization/WebSite/Article) را بگذار.
جزییات پیادهسازی
در این بخش، هر گام را با نمونهکد بررسی میکنیم.
نمونهٔ تنظیم متادیتا در Layout
ابتدا متادیتای پایه را در app/layout.tsx اضافه کنید تا URLهای نسبی (مثل OG image) با metadataBase به آدرس کامل تبدیل شوند.
export const metadata = {
metadataBase: new URL("https://www.webdesignwithsina.ir"),
title: { default: "WebDesignBySina", template: "%s | WebDesignBySina" },
description: "SEO-first websites with Next.js + Django.",
openGraph: {
type: "website",
url: "https://www.webdesignwithsina.ir",
siteName: "WebDesignBySina",
images: [{ url: "/og/cover.jpg", width: 1200, height: 630 }]
},
twitter: { card: "summary_large_image", images: ["/og/cover.jpg"] }
} as const
canonical مطلق در صفحات داینامیک
برای صفحات پارامتری (مثل بلاگ)، canonical را در generateMetadata به صورت مطلق بسازید.
import type { Metadata } from "next";
export async function generateMetadata({ params }: { params: { slug: string } }): Promise<Metadata> {
const url = `https://www.webdesignwithsina.ir/blog/${params.slug}`;
return { alternates: { canonical: url } };
}
اگر metadataBase نداری، canonical نسبی نگذار؛ لینک را مطلق بنویس.
robots.txt و sitemap.xml در App Router
از Routeهای مخصوص استفاده کن تا robots.txt و sitemap.xml تولید شوند.
import type { MetadataRoute } from "next";
export default function robots(): MetadataRoute.Robots {
return {
rules: { userAgent: "*", allow: "/", disallow: "/admin/" },
sitemap: "https://www.webdesignwithsina.ir/sitemap.xml"
};
}
تولید sitemap
یک سایتمپ سادهی استاتیک یا داینامیک بساز.
import type { MetadataRoute } from "next";
export default function sitemap(): MetadataRoute.Sitemap {
const baseUrl = "https://www.webdesignwithsina.ir";
return [
{ url: baseUrl, lastModified: new Date(), changeFrequency: "daily", priority: 1.0 },
{ url: `${baseUrl}/blog`, lastModified: new Date(), changeFrequency: "weekly", priority: 0.8 }
];
}
دادههای ساختیافته (JSON-LD)
Organization/WebSite را در Layout و Article را در صفحهٔ بلاگ با <script type="application/ld+json"> اضافه کن.
<script type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify({
"@context": "https://schema.org",
"@type": "Organization",
"name": "WebDesignBySina",
"url": "https://www.webdesignwithsina.ir",
"logo": "https://www.webdesignwithsina.ir/logo.png"
}) }} />
<script type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify({
"@context": "https://schema.org",
"@type": "WebSite",
"url": "https://www.webdesignwithsina.ir",
"name": "WebDesignBySina",
"potentialAction": {
"@type": "SearchAction",
"target": "https://www.webdesignwithsina.ir/search?query={q}",
"query-input": "required name=q"
}
}) }} />
متادیتای مقاله و Article JSON-LD
برای صفحات بلاگ، علاوهبر canonical، متادیتای Article و JSON-LD مقاله را هم اضافه کن تا از date و lastModified استفاده شود.
import type { Metadata } from "next";
import { notFound } from "next/navigation";
// فرض: getPost(slug) عنوان/خلاصه/کاور/تاریخها را میدهد
async function getPost(slug: string) {
// ...
}
export async function generateMetadata({ params }: { params: { slug: string } }): Promise<Metadata> {
const post = await getPost(params.slug);
if (!post) return notFound();
const url = `https://www.webdesignwithsina.ir/blog/${params.slug}`;
return {
title: post.title,
description: post.description,
alternates: { canonical: url },
openGraph: {
type: "article",
url,
title: post.title,
description: post.description,
images: [{ url: post.cover ?? "/og/blog/nexus.webp", width: 1200, height: 630 }],
publishedTime: post.date,
modifiedTime: post.lastModified
},
twitter: { card: "summary_large_image", title: post.title, description: post.description, images: [post.cover ?? "/og/blog/nexus.webp"] }
};
}
export default async function Page({ params }: { params: { slug: string } }) {
const post = await getPost(params.slug);
if (!post) return notFound();
return (
<article>
{/* ... محتوا ... */}
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify({
"@context": "https://schema.org",
"@type": "Article",
"headline": post.title,
"description": post.description,
"image": post.cover ? `https://www.webdesignwithsina.ir${post.cover}` : undefined,
"datePublished": post.date,
"dateModified": post.lastModified,
"mainEntityOfPage": { "@type": "WebPage", "@id": `https://www.webdesignwithsina.ir/blog/${params.slug}` }
}) }}
/>
</article>
);
}
پشتیبانی چندزبانه و hreflang (i18n SEO)
در next.config.js شئ i18n را تنظیم کنید تا زبانها و زبان پیشفرض مشخص شوند. سپس با alternates.languages، تگهای hreflang را بهصورت خودکار تولید کنید.
module.exports = {
i18n: {
locales: ["fa", "en"],
defaultLocale: "fa",
},
};
استفاده از alternates.languages در متادیتای Layout
برای صفحات ریشه (مثل صفحهٔ اصلی)، نمونهٔ زیر را در app/layout.tsx تنظیم کنید:
export const metadata = {
metadataBase: new URL("https://www.webdesignwithsina.ir"),
alternates: {
canonical: "/",
languages: {
"fa-IR": "/", // نسخه فارسی – صفحه اصلی
"en-US": "/en" // نسخه انگلیسی – صفحه اصلی انگلیسی
}
},
// ... سایر تنظیمات metadata ...
} as const;
alternates.languages برای یک صفحه (مثلاً درباره ما)
برای صفحات مشخص (مثل درباره ما) میتوانید مستقیماً در Metadata همان صفحه تنظیم کنید:
export const metadata = {
alternates: {
canonical: "/about",
languages: {
"fa-IR": "/about",
"en-US": "/en/about"
}
}
};
hreflang با alternates.languages برای صفحات داینامیک
در صفحات پارامتری (مثل بلاگ)، نسخههای زبانی را بر اساس slug بسازید:
import type { Metadata } from "next";
export async function generateMetadata({ params }: { params: { slug: string } }): Promise<Metadata> {
const base = "https://www.webdesignwithsina.ir";
const urlFa = `${base}/blog/${params.slug}`;
const urlEn = `${base}/en/blog/${params.slug}`;
return {
alternates: {
canonical: urlFa,
languages: {
"fa-IR": urlFa,
"en-US": urlEn
}
}
};
}
خروجی تگهای head
پس از تنظیم بالا، تگهای زیر در head درج میشوند:
<link rel=\"alternate\" hreflang=\"fa-IR\" href=\"https://www.webdesignwithsina.ir/about\" />
<link rel=\"alternate\" hreflang=\"en-US\" href=\"https://www.webdesignwithsina.ir/en/about\" />
<link rel=\"canonical\" href=\"https://www.webdesignwithsina.ir/about\" />
نکات تکمیلی i18n
- محتوای متنی، متادیتا (Title/Description) و حتی
langمطابق زبان هر نسخه باشد. در Layout میتوانید<html lang={locale}>را تنظیم کنید. - اگر برای هر زبان دامنهٔ جداگانه دارید، بهجای مسیر نسبی، URL کامل همان دامنه را بدهید.
- برای نسخهٔ پیشفرض هم یک
hreflangبگذارید (مثلاًfa-IR). در صورت نیاز بهx-default، میتوانید آن را دستی داخل<head>اضافه کنید. - لینک تعویض زبان در سایت قرار دهید؛ مثال با Next
<Link>:
import Link from "next/link";
<Link href="/about" locale="en">English</Link>
<Link href="/about" locale="fa">فارسی</Link>بهینهسازی Core Web Vitals (سرعت و تجربه)
علاوه بر تگها و موارد فنی سئو، سرعت و عملکرد سایت نقش مهمی در رتبه دارد. گوگل با Core Web Vitals تجربه کاربری را میسنجد. در زیر، شاخصها و راهکارهای عملی Next.js را بهصورت بخشبندیشده میبینید.
شاخصها و آستانههای پیشنهادی
- LCP (Largest Contentful Paint): زمان نمایش بزرگترین محتوای قابلمشاهده (هدف: < 2.5s)
- FID (First Input Delay): معیار قدیمی تعامل اولیه؛ از 2024 با INP جایگزین شده
- CLS (Cumulative Layout Shift): جابهجایی تجمعی چیدمان (هدف: < 0.1)
- INP (Interaction to Next Paint): سنجهٔ پاسخگویی به تعاملها در طول جلسه (هدف: < 200ms)
بهینهسازی تصاویر
- از کامپوننت
<Image>در Next.js استفاده کنید تاwidth/heightو lazy-load بهصورت خودکار مدیریت شود. - برای قهرمان صفحه (Hero/LCP) از تصاویر بهینه و ترجیحاً فرمتهای نوین (WebP/AVIF) استفاده کنید.
- Placeholder (blur) یا اندازهٔ ثابت تصویر را تنظیم کنید تا CLS کاهش یابد.
فونتها و نمایش متن
- از بهینهسازی فونت Next (
next/font) یاfont-display: swapاستفاده کنید تا تأخیر نمایش (FOUT) کم شود. - زیرمجموعهسازی (subsetting) فونت و پرهیز از وزنهای غیرضروری به کاهش JS/CSS کمک میکند.
مدیریت اسکریپتها و کتابخانههای ثالث
- اسکریپتهای غیرضروری اولیه را با
<Script strategy=\"lazyOnload\">به تعویق بیندازید. - برای اسکریپتهایی که باید قبل از تعامل آماده باشند (اما ضروری برای SSR نیستند)، بسته به نیاز از
strategy=\"beforeInteractive\"یاstrategy=\"afterInteractive\"استفاده کنید. - تعداد اسکریپتهای «قبل از تعاملی» را کم نگه دارید؛ افزایش آنها میتواند INP را بدتر کند.
کاهش CLS (پرش چیدمان)
- برای تصاویر/ویدیوها اندازهٔ ثابت یا Placeholder بگذارید.
- برای بنرها/نوار اعلان/تبلیغات فضا رزرو کنید تا واردشدن ناگهانی باعث پرش نشود.
- از بارگذاری تنبلِ محتواهای بالایتاپ (Above the Fold) که باعث جابهجایی میشود، خودداری کنید.
تفکیک کد و بارگذاری تنبل
- Next.js بهصورت خودکار code-splitting انجام میدهد؛ اما ماژولهای سنگین را با
dynamic import()فقط وقتی لازم شد لود کنید. - این کار حجم اولیه JS را کاهش میدهد و TTFB/LCP را بهبود میکند.
انتخاب استراتژی رندر (ISR/SSG در برابر CSR)
- تا حد امکان از ISR/SSG استفاده کنید تا محتوای اولیه سریع و قابل ایندکس ارائه شود.
- App Router (13+) بهصورت پیشفرض سرور-رندر است و فقط بخشهای تعاملی بعداً هیدریت میشوند—از این مزیت برای سئو بهره ببرید.
- CSR کامل را فقط در صورت ضرورت بهکار ببرید.
مانیتورینگ و تست
- پس از استقرار، با Lighthouse و PageSpeed Insights تست بگیرید.
- در Google Search Console گزارش Core Web Vitals (CrUX) را دورهای بررسی کنید و صفحات ضعیف را بهبود دهید.
- در صورت نیاز، گزارش داخلی Web Vitals را در ریشهٔ اپ پیادهسازی کنید و متریکها را به آنالیتیکس بفرستید.
جمعبندی
تجربهٔ سریع و روان بخشی از سئو است. تنها داشتن متاتگهای درست کافی نیست؛ با بهینهسازی تصاویر، فونتها، اسکریپتها و استراتژی رندر، به آستانههای LCP/CLS/INP برسید و بهصورت مستمر پایش کنید.
مانیتورینگ و گزارشگیری Web Vitals
- پس از انتشار، با Lighthouse و PageSpeed Insights ارزیابی کن.
- گزارشهای Core Web Vitals در Google Search Console (CrUX) را دورهای بررسی کن.
- در صورت نیاز از جمعآوری داخلی با
useReportWebVitalsاستفاده کن تا متریکها را به سرویس آنالیتیکس خودت بفرستی.
اشتباهات رایج
در مسیر پیادهسازی سئوی Next.js، چند خطای پرتکرار دیده میشود. در زیر، هر خطا را بههمراه توضیح کوتاه و راهحل عملی آوردهایم.
تصویر OG نامناسب
- تصویر خیلی کوچک یا با نسبت نادرست باعث برش/پیکسلشدن در کارتهای پیشنمایش میشود.
- پیشنهاد: ابعاد 1200×630 با کنتراست بالا و موضوع واضح (لوگو یا تصویری که خلاصهٔ محتوا را برساند).
- اگر روی تصویر متن دارید، اندازه/رنگ متن باید خوانا باشد.
- ویژگی
og:image:altرا نیز تنظیم کنید تا توصیفی از تصویر به خزندهها بدهید.
canonical نسبی یا ناقص در صفحات داینامیک
- ننوشتن canonical یا قراردادن نسخهٔ نسبی/نادرست، به مشکل محتوای تکراری منجر میشود.
- Next.js خودش بهصورت خودکار canonical اضافه نمیکند؛ باید آن را تعریف کنید.
- راهحل: برای هر صفحهٔ یکتا، یک canonical مطلق و کامل (شامل
httpsو دامنه) بگذارید—خصوصاً در صفحات پارامتری (مثل بلاگ).
بیتوجهی به INP/CLS و جایگذاری نادرست اسکریپتها
- تمرکز صرف روی متاتگها و بیتوجهی به عملکرد میتواند نمرهٔ Core Web Vitals را خراب کند.
- اسکریپتهای آنالیتیکس/کتابخانههای حجیم در
<head>یا بدونasync/def erرندر/تعامل را بلوکه میکنند. - iframeهای چت/ویدیو اگر بهینه نشوند، INP را بدتر میکنند.
- راهحلها:
- اسکریپتهای غیرضروری را تعویق دهید (مثلاً با
strategy="lazyOnload"). - برای المانهایی که پرش ایجاد میکنند، ارتفاع ثابت/Placeholder درنظر بگیرید یا از Skeleton استفاده کنید تا CLS کنترل شود.
- عملکرد (Performance) را بخش جدانشدنی سئو بدانید و پیوسته آن را پایش کنید.
- اسکریپتهای غیرضروری را تعویق دهید (مثلاً با
جمعبندی
با دوری از این خطاها، تلاشهای سئوی شما نتیجهٔ بهتری میگیرد و سایت در بهترین حالت برای موتورهای جستجو عرضه میشود.
چکلیست نهایی
- تنظیم کامل متادیتا: Title/Description + OG/Twitter با تصویر اشتراکگذاری بهینه
- canonical مطلق برای همهٔ صفحات (خصوصاً داینامیک)
- robots.txt و sitemap.xml درست؛ و ثبت sitemap در GSC
- JSON-LD (Organization/WebSite/Article …) برای Rich Results
- پایش و بهبود Core Web Vitals (LCP/INP/CLS) و مدیریت اسکریپتها/تصاویر/فونتها
زمانبندی انتشار
— انتشار اولیه: 2025-06-20 • آخرین بروزرسانی: 2025-07-15
سوالی داری یا پروژهای در ذهنته؟
با ما تماس بگیر تا با هم بهترین مسیر رو بچینیم.