feat: enhance SEO for listing and specialty pages, fix search autocomplete issue

This commit is contained in:
hamed
2026-07-20 10:26:03 +03:30
parent 9011b230b3
commit 30c3fe8637
14 changed files with 460 additions and 69 deletions
+7 -2
View File
@@ -7,6 +7,7 @@ import { getStateInfo } from "@/lib/getStateInfo";
import { getRequestOrigin } from "@/lib/getCanonicalUrl";
import { resolveCityDisplayName } from "@/lib/domainHelpers";
import { buildSpecialtyFaq, buildSpecialtyIntro } from "@/lib/specialtyContent";
import { isCategorySpecialty } from "@/lib/specialtyIndexing";
import { safeJsonLd } from "@/lib/sanitize";
import { fetchReq } from "@/lib/req";
import { isNextRedirectError } from "@/lib/maintenance";
@@ -58,10 +59,14 @@ export async function generateMetadata({ params }) {
// داخلی‌اش دنبال شوند. به‌محض افزوده‌شدن اولین پزشک، خودکار ایندکس‌پذیر می‌شود.
const { total } = await getDoctors(specialty.id, isRoot ? null : matchedCity?.id);
// دستهٔ سطح‌بالا (دارای زیرشاخهٔ فعال) محتوای مستقلی ندارد و با فرزندانش روی همان
// کوئری رقابت می‌کند؛ صفحهٔ قابل‌ایندکس، همان زیرشاخه است.
const noindex = isCategorySpecialty(specialty) || total === 0;
return {
title,
description,
...(total === 0 && { robots: { index: false, follow: true } }),
...(noindex && { robots: { index: false, follow: true } }),
// C1-a — صفحهٔ فرود تخصص per-domain است؛ canonical لایهٔ layout (self) درست است.
openGraph: { title, description, images: [image] },
twitter: { card: "summary_large_image", title, description, images: [image] },
@@ -83,7 +88,7 @@ async function SpecialtyDetail({ params }) {
);
const intro = buildSpecialtyIntro(specialty.name, cityName, total);
const faq = buildSpecialtyFaq(specialty.name, cityName, total);
const faq = buildSpecialtyFaq(specialty.name, cityName, total, { isRoot });
const pageUrl = `${origin}/specialties/${specialty.slug}`;
const pageJsonLd = {