feat(metadata): enhance SEO by adding Open Graph and Twitter metadata across various pages
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
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
import { Skeleton } from "@mui/material";
|
||||
|
||||
export default function Loading() {
|
||||
return (
|
||||
<div className="p-4 flex flex-col gap-4" dir="rtl">
|
||||
<Skeleton variant="rounded" height={280} className="!rounded-lg" />
|
||||
<Skeleton variant="rounded" width={220} height={28} />
|
||||
<Skeleton variant="rounded" height={20} className="!w-full" />
|
||||
<Skeleton variant="rounded" height={20} className="!w-full" />
|
||||
<Skeleton variant="rounded" height={20} width={300} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
+35
-6
@@ -1,3 +1,4 @@
|
||||
import { cache } from "react";
|
||||
import BlogPage from "@/components/blog";
|
||||
import Layout from "@/components/layout/StLayout";
|
||||
import { fetchReq } from "@/lib/req";
|
||||
@@ -5,16 +6,28 @@ import { getStateInfo } from "@/lib/getStateInfo";
|
||||
import { normalizeBlog, imageUrl } from "@/helper";
|
||||
|
||||
const FALLBACK_IMG = "https://www.nobat724.com/assets/images/logo.png";
|
||||
const API_URL = process.env.NEXT_PUBLIC_API_URL;
|
||||
|
||||
const getBlog = cache(async (slug) => {
|
||||
try {
|
||||
const res = await fetch(`${API_URL}/api/v1/blog/${slug}`, {
|
||||
next: { revalidate: 3600, tags: [`blog-${slug}`] },
|
||||
});
|
||||
if (!res.ok) return null;
|
||||
const json = await res.json();
|
||||
return json?.data?.data ?? null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
export async function generateMetadata({ params }) {
|
||||
const { slug } = await params;
|
||||
const API_URL = process.env.NEXT_PUBLIC_API_URL;
|
||||
const { matchedCity } = await getStateInfo();
|
||||
const siteName = matchedCity?.site_name || "نوبت 724";
|
||||
|
||||
try {
|
||||
const res = await fetchReq(`${API_URL}/api/v1/blog/${slug}`);
|
||||
const blog = res?.data?.data;
|
||||
const blog = await getBlog(slug);
|
||||
if (!blog) return {};
|
||||
|
||||
const title = `${blog.title} | ${siteName}`;
|
||||
@@ -50,10 +63,8 @@ export async function generateMetadata({ params }) {
|
||||
|
||||
async function Blog({ params }) {
|
||||
const { slug } = await params;
|
||||
const API_URL = process.env.NEXT_PUBLIC_API_URL;
|
||||
|
||||
const res = await fetchReq(`${API_URL}/api/v1/blog/${slug}`);
|
||||
const blog = normalizeBlog(res?.data?.data);
|
||||
const blog = normalizeBlog(await getBlog(slug));
|
||||
|
||||
let relatedBlogs = [];
|
||||
const relatedResponse = await fetchReq(
|
||||
@@ -77,6 +88,18 @@ async function Blog({ params }) {
|
||||
}
|
||||
: null;
|
||||
|
||||
const breadcrumbJsonLd = blog
|
||||
? {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "BreadcrumbList",
|
||||
itemListElement: [
|
||||
{ "@type": "ListItem", position: 1, name: "خانه", item: "https://www.nobat724.com" },
|
||||
{ "@type": "ListItem", position: 2, name: "مقالات", item: "https://www.nobat724.com/blogs" },
|
||||
{ "@type": "ListItem", position: 3, name: blog.title },
|
||||
],
|
||||
}
|
||||
: null;
|
||||
|
||||
return (
|
||||
<>
|
||||
{jsonLd && (
|
||||
@@ -85,6 +108,12 @@ async function Blog({ params }) {
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
||||
/>
|
||||
)}
|
||||
{breadcrumbJsonLd && (
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(breadcrumbJsonLd) }}
|
||||
/>
|
||||
)}
|
||||
<Layout>
|
||||
<BlogPage blog={blog} blogs={relatedBlogs} />
|
||||
</Layout>
|
||||
|
||||
Reference in New Issue
Block a user