feat(blog): implement loading and error handling components for blog pages feat(clinic): add loading and error handling components for clinic pages feat(doctor): create loading and error handling components for doctor pages feat(clinics): add loading component for clinics page feat(specialties): improve metadata for specialties page with Open Graph and Twitter images feat(layout): add structured data for Organization and WebSite in layout fix(middleware): restrict middleware execution to specific routes to improve performance chore(audit): add comprehensive SEO and performance audit documentation
127 lines
4.3 KiB
JavaScript
127 lines
4.3 KiB
JavaScript
import "./globals.css";
|
|
import ThemeRegistry from "./component/ThemeRegistry";
|
|
import { Providers } from "./Providers";
|
|
import { GoogleAnalytics } from "@next/third-parties/google";
|
|
import { GoogleTagManager } from "@next/third-parties/google";
|
|
import "react-toastify/dist/ReactToastify.css";
|
|
import CustomToastify from "./CustomToastify";
|
|
import { ProvinceProvider } from "@/context/ProvinceProvider";
|
|
import { getStateInfo } from "@/lib/getStateInfo";
|
|
import { getCanonicalUrl } from "@/lib/getCanonicalUrl";
|
|
|
|
export async function generateMetadata() {
|
|
const { matchedCity } = await getStateInfo();
|
|
|
|
const canonicalUrl = await getCanonicalUrl();
|
|
|
|
const title = matchedCity ? matchedCity.title : "نوبت724";
|
|
const description = matchedCity?.description || "نوبت 724 - سیستم آنلاین نوبتدهی برای پزشکان و کلینیکها. با استفاده از نوبت 724، به راحتی نوبت پزشکی خود را به صورت آنلاین رزرو کنید و از خدمات سریع و کارآمد ما بهرهمند شوید";
|
|
|
|
const baseMetadata = {
|
|
title,
|
|
description,
|
|
keywords: matchedCity
|
|
? matchedCity.keywords
|
|
: "نوبت 724, نوبت دهی, رزرو نوبت, پزشک, پزشکی, کلینیک, بیمارستان, نوبت آنلاین, سیستم نوبت دهی, سیستم نوبت دهی آنلاین, سیستم نوبت دهی پزشکی, سیستم نوبت دهی کلینیک, سیستم نوبت دهی بیمارستان, سیستم نوبت دهی آنلاین پزشکی, سیستم نوبت دهی آنلاین کلینیک, سیستم نوبت دهی آنلاین بیمارستان",
|
|
openGraph: {
|
|
title,
|
|
description,
|
|
type: "website",
|
|
locale: "fa_IR",
|
|
siteName: matchedCity?.site_name || "نوبت 724",
|
|
images: ["https://www.nobat724.com/assets/images/logo.png"],
|
|
},
|
|
twitter: {
|
|
card: "summary_large_image",
|
|
title,
|
|
description,
|
|
images: ["https://www.nobat724.com/assets/images/logo.png"],
|
|
},
|
|
};
|
|
|
|
// Add noindex meta tag when DEV_MODE is TRUE
|
|
if (process.env.DEV_MODE === 'TRUE') {
|
|
baseMetadata.robots = {
|
|
index: false,
|
|
follow: false,
|
|
nocache: true,
|
|
googleBot: {
|
|
index: false,
|
|
follow: false,
|
|
noimageindex: true,
|
|
'max-video-preview': -1,
|
|
'max-image-preview': 'large',
|
|
'max-snippet': -1,
|
|
},
|
|
};
|
|
}
|
|
|
|
// Add canonical URL only if we're not on the main domain and matchedCity domain is not nobat724.com
|
|
if (canonicalUrl && (!matchedCity || matchedCity.domain !== 'nobat724.com')) {
|
|
baseMetadata.alternates = {
|
|
canonical: canonicalUrl,
|
|
};
|
|
}
|
|
|
|
return baseMetadata;
|
|
}
|
|
|
|
export default async function RootLayout({ children }) {
|
|
const { matchedCity } = await getStateInfo();
|
|
const siteName = matchedCity?.site_name || "نوبت 724";
|
|
const siteUrl = "https://www.nobat724.com";
|
|
|
|
const organizationJsonLd = {
|
|
"@context": "https://schema.org",
|
|
"@type": "Organization",
|
|
name: siteName,
|
|
url: siteUrl,
|
|
logo: `${siteUrl}/assets/images/logo.png`,
|
|
};
|
|
|
|
const websiteJsonLd = {
|
|
"@context": "https://schema.org",
|
|
"@type": "WebSite",
|
|
url: siteUrl,
|
|
name: siteName,
|
|
potentialAction: {
|
|
"@type": "SearchAction",
|
|
target: `${siteUrl}/doctors?search={search_term_string}`,
|
|
"query-input": "required name=search_term_string",
|
|
},
|
|
};
|
|
|
|
return (
|
|
<html lang="fa" dir="rtl" suppressHydrationWarning>
|
|
<head>
|
|
<meta
|
|
name="viewport"
|
|
content="width=device-width,initial-scale=1"
|
|
/>
|
|
<script
|
|
type="application/ld+json"
|
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(organizationJsonLd) }}
|
|
/>
|
|
<script
|
|
type="application/ld+json"
|
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(websiteJsonLd) }}
|
|
/>
|
|
</head>
|
|
<ThemeRegistry>
|
|
{process.env.DEV_MODE === 'FALSE' && (
|
|
<GoogleTagManager gtmId="GTM-NXBSV7GS" />
|
|
)}
|
|
<body className="bg-[#FAFAFA]">
|
|
<ProvinceProvider>
|
|
<Providers>{children}</Providers>
|
|
</ProvinceProvider>
|
|
<CustomToastify />
|
|
</body>
|
|
{process.env.DEV_MODE === 'FALSE' && (
|
|
<GoogleAnalytics gaId="G-HG3RZ1PJS5" />
|
|
)}
|
|
</ThemeRegistry>
|
|
</html>
|
|
);
|
|
}
|