الملفات
gracesalmoun/data/seo.ts
2026-05-04 13:04:00 +00:00

284 أسطر
7.7 KiB
TypeScript

import type { Metadata } from "next";
import { englishPortfolioContent, getPortfolioContent, sharedProfile, type Language } from "@/data/portfolio";
import { absoluteUrl, siteName } from "@/data/site-config";
const primaryEnglishName = sharedProfile.founderNameEn;
const fullEnglishName = sharedProfile.fullNameEn;
const englishAlternateNames = sharedProfile.alternateNamesEn;
const arabicName = sharedProfile.founderNameAr;
const sharedKeywords = [
"Grace Salmoun",
"Grace Butrus Salmoun",
"Grace Salamoun",
"architecture portfolio",
"architectural engineer",
"architectural design",
"urban rehabilitation",
"landscape design",
"shop drawings",
"architectural visualization",
"Damascus architect",
];
const localizedKeywords: Record<Language, string[]> = {
en: ["portfolio architect", "presentation boards", "mixed-use towers", "hospitality design"],
ar: ["بورتفوليو معماري", "مهندسة معمارية", "تصميم معماري", "إعادة تأهيل عمراني"],
};
function getLocale(language: Language) {
return language === "ar" ? "ar_SY" : "en_US";
}
function getAlternateLocales(language: Language) {
return language === "ar" ? ["en_US"] : ["ar_SY"];
}
function getHomePath(language: Language) {
return language === "ar" ? "/ar" : "/";
}
function getResumePath(language: Language) {
return language === "ar" ? "/ar/resume" : "/resume";
}
function getOgImage(language: Language) {
return {
url: absoluteUrl(sharedProfile.heroImage),
alt:
language === "ar"
? "معاينة بورتفوليو غريس سلمون"
: "Portfolio preview for Grace Salmoun",
};
}
function buildMetadata({
language,
title,
description,
canonicalPath,
pageType,
}: {
language: Language;
title: string;
description: string;
canonicalPath: string;
pageType: "website" | "profile";
}): Metadata {
const ogImage = getOgImage(language);
return {
title,
description,
keywords: [...sharedKeywords, ...localizedKeywords[language]],
authors: [{ name: primaryEnglishName }],
creator: primaryEnglishName,
publisher: primaryEnglishName,
category: "architecture portfolio",
alternates: {
canonical: canonicalPath,
languages: {
en: canonicalPath.includes("/resume") ? "/resume" : "/",
ar: canonicalPath.includes("/resume") ? "/ar/resume" : "/ar",
"x-default": "/",
},
},
robots: {
index: true,
follow: true,
googleBot: {
index: true,
follow: true,
"max-image-preview": "large",
"max-snippet": -1,
"max-video-preview": -1,
},
},
openGraph: {
title,
description,
url: absoluteUrl(canonicalPath),
siteName,
locale: getLocale(language),
alternateLocale: getAlternateLocales(language),
type: pageType,
images: [ogImage],
},
twitter: {
card: "summary_large_image",
title,
description,
images: [ogImage.url],
},
};
}
export function getDefaultSeoMetadata(): Metadata {
const title = englishPortfolioContent.meta.title;
const description = englishPortfolioContent.meta.description;
const ogImage = getOgImage("en");
return {
title,
description,
applicationName: siteName,
authors: [{ name: primaryEnglishName }],
creator: primaryEnglishName,
publisher: primaryEnglishName,
keywords: [...sharedKeywords, ...localizedKeywords.en],
category: "architecture portfolio",
referrer: "origin-when-cross-origin",
robots: {
index: true,
follow: true,
googleBot: {
index: true,
follow: true,
"max-image-preview": "large",
"max-snippet": -1,
"max-video-preview": -1,
},
},
openGraph: {
title,
description,
url: absoluteUrl("/"),
siteName,
locale: "en_US",
alternateLocale: ["ar_SY"],
type: "website",
images: [ogImage],
},
twitter: {
card: "summary_large_image",
title,
description,
images: [ogImage.url],
},
};
}
export function getHomeMetadata(language: Language): Metadata {
const t = getPortfolioContent(language);
return buildMetadata({
language,
title: t.meta.title,
description: t.meta.description,
canonicalPath: getHomePath(language),
pageType: "website",
});
}
export function getResumeMetadata(language: Language): Metadata {
const t = getPortfolioContent(language);
const title = language === "ar" ? `السيرة الذاتية | ${t.meta.title}` : `Resume | ${t.meta.title}`;
return buildMetadata({
language,
title,
description: t.resume.description,
canonicalPath: getResumePath(language),
pageType: "profile",
});
}
export function getHomeStructuredData(language: Language) {
const t = getPortfolioContent(language);
const name = language === "ar" ? sharedProfile.founderNameAr : sharedProfile.founderNameEn;
const address = language === "ar" ? sharedProfile.addressAr : sharedProfile.address;
return [
{
"@context": "https://schema.org",
"@type": "WebSite",
name: siteName,
alternateName: [`${fullEnglishName} Portfolio`, "Grace Salamoun Portfolio"],
url: absoluteUrl("/"),
inLanguage: ["en", "ar"],
},
{
"@context": "https://schema.org",
"@type": "Person",
name,
givenName: "Grace",
additionalName: "Butrus",
familyName: "Salmoun",
alternateName: language === "ar" ? [primaryEnglishName, fullEnglishName, ...englishAlternateNames] : [fullEnglishName, arabicName, ...englishAlternateNames],
url: absoluteUrl(getHomePath(language)),
image: absoluteUrl(sharedProfile.heroImage),
jobTitle: t.ui.architectureEngineer,
description: t.meta.description,
email: sharedProfile.email,
telephone: sharedProfile.phone,
address: {
"@type": "PostalAddress",
addressLocality: address,
addressCountry: "SY",
},
sameAs: [sharedProfile.facebookHref],
knowsAbout: [...t.craft.skills.slice(0, 4), ...t.sectors.categories.slice(0, 4)],
},
{
"@context": "https://schema.org",
"@type": "CollectionPage",
name: t.meta.title,
description: t.meta.description,
url: absoluteUrl(getHomePath(language)),
inLanguage: language,
isPartOf: {
"@type": "WebSite",
name: siteName,
url: absoluteUrl("/"),
},
about: {
"@type": "Person",
name,
},
},
];
}
export function getResumeStructuredData(language: Language) {
const t = getPortfolioContent(language);
const name = language === "ar" ? sharedProfile.founderNameAr : sharedProfile.founderNameEn;
const title = language === "ar" ? `السيرة الذاتية | ${name}` : `Resume | ${name}`;
const person = {
"@context": "https://schema.org",
"@type": "Person",
name,
givenName: "Grace",
additionalName: "Butrus",
familyName: "Salmoun",
alternateName:
language === "ar"
? [primaryEnglishName, fullEnglishName, ...englishAlternateNames]
: [fullEnglishName, arabicName, ...englishAlternateNames],
url: absoluteUrl(getHomePath(language)),
email: sharedProfile.email,
telephone: sharedProfile.phone,
image: absoluteUrl(sharedProfile.heroImage),
jobTitle: t.ui.architectureEngineer,
sameAs: [sharedProfile.facebookHref],
};
return [
person,
{
"@context": "https://schema.org",
"@type": "ProfilePage",
name: title,
description: t.resume.description,
url: absoluteUrl(getResumePath(language)),
inLanguage: language,
isPartOf: {
"@type": "WebSite",
name: siteName,
url: absoluteUrl("/"),
},
mainEntity: person,
about: person,
},
];
}