متادیتا و OG در Next.js: سئو تمیز بدون هاردکد
نویسنده: آرش لطیفی
راهنمای عملی Metadata API در Next.js — از title و description تا Open Graph، توییتر کارت، canonical و sitemap پویا با generateMetadata.
خلاصه: سئو را از هاردکد نجات بده — با
generateMetadataوsitemap.tsهر صفحه عنوان، توضیح و OG اختصاصی میگیرد و گوگل و تلگرام درست نمایشش میدهند.
چرا Metadata API مهم شد
قبلا برای هر صفحه Head دستی مینوشتیم و og:image را هاردکد میکردیم. در Next.js 13 به بعد، آبجکت metadata جایگزین شد و همه چیز — title، description، canonical، openGraph و twitter — تایپدار و متمرکز شد. نتیجه: سئوی یکدست، پیشنمایش درست در تلگرام و واتساپ، و بدون تکرار Head در هر فایل.
اگر مرز سرور و کلاینت را درست نگه داری، این متادیتا فقط روی سرور ساخته میشود و به باندل کلاینت اضافه نمیشود. برای درک مرز، آلودگی RSC و use-client را ببین و برای کش و رندر، کش و PPR در Next 15 مکمل خوبی است.
ساختار تمیز: layout و generateMetadata
در app/layout.tsx متادیتای پایه را بگذار، در هر page.tsx با generateMetadata آن را بازنویسی کن:
نکته: metadataBase حتما URL کامل باشد تا لینکهای نسبی OG درست ساخته شوند.
تصویر OG پویا با ImageResponse
برای هر مقاله یک opengraph-image.tsx بساز تا تصویر ۱۲۰۰×۶۳۰ سرور-ساید ساخته شود:
این فایل به طور خودکار در /blog/[slug]/opengraph-image سرو میشود و نیازی به openGraph.images دستی نیست اگر همین قرارداد را نگه داری.
sitemap و robots پویا
به جای sitemap.xml دستی:
یادت باشد sitemap.ts باید همه URLهای نهایی — با /fa یا بدون — را پوشش دهد؛ بسته به i18n پروژهات.
| اشتباه رایج | چه میشود | راه درست |
| --- | --- | --- |
| هاردکد og:image ثابت برای همه صفحات | پیشنمایش تکراری در تلگرام | generateMetadata یا opengraph-image.tsx پویا |
| بدون metadataBase | لینک OG نسبی میماند و شکسته میشود | metadataBase: new URL("https://...") |
| title بدون template | عنوانها یکنواخت و طولانی | template: "%s | برند" در layout |
| sitemap.xml دستی قدیمی | صفحات جدید ایندکس نمیشوند | sitemap.ts داینامیک از دیتابیس/MDX |
چکلیست سئو متادیتا
- [x]
metadataBaseوalternates.canonicalرا درlayoutست کردم - [x]
generateMetadataبرای صفحات داینامیک نوشتم وnotFoundرا هندل کردم - [ ]
opengraph-image.tsxبا سایز ۱۲۰۰×۶۳۰ اضافه کردم و با تلگرام تست کردم - [ ]
sitemap.tsوrobots.tsرا داینامیک کردم - [ ] عنوانها زیر ۶۰ کاراکتر و توضیحات زیر ۱۵۵ کاراکتر نگه داشتم
- [ ]
twitter.cardراsummary_large_imageگذاشتم
کیس کوتاه: یک سایت فروشگاهی با ۸۰ محصول، OG ثابت داشت — همه اشتراکها یک عکس نشان میداد. بعد از افزودن generateMetadata و opengraph-image.tsx برای هر محصول، نرخ کلیک از تلگرام ۲۲٪ بالا رفت و خطای Missing og:image در سرچ کنسول صفر شد. برای فرمها و اعتبارسنجی محصول، تیم از اعتبارسنجی فرم با Zod استفاده کرد تا داده ورودی قبل از ساخت متادیتا تمیز بماند.
FAQ
Q: آیا میتوانم metadata را در Client Component بگذارم؟
نه. metadata و generateMetadata فقط در Server Component کار میکنند. اگر صفحهات use client دارد، متادیتا را به page.tsx والد منتقل کن.
Q: تصویر OG را از کجا سرو کنم؟
سادهترین راه opengraph-image.tsx کنار page.tsx است. اگر CDN داری، URL مطلق بده و width و height را مشخص کن تا کراولرها درست برش بزنند.
Q: canonical را برای صفحات فارسی و انگلیسی چطور بگذارم؟
برای هر لوکال یک canonical جدا با URL همان زبان بگذار و با alternates.languages به زبان دیگر اشاره کن. از canonical مشترک برای دو زبان استفاده نکن.