udpate for coming soon
This commit is contained in:
@@ -22,3 +22,7 @@ export function getDictionary(locale: Locale): Dictionary {
|
||||
export function getDirection(locale: Locale): "rtl" | "ltr" {
|
||||
return locale === "ar" ? "rtl" : "ltr";
|
||||
}
|
||||
|
||||
export function getLocaleName(locale: Locale): string {
|
||||
return locale === "ar" ? "العربية" : "English";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
import type { Metadata } from "next";
|
||||
import { getDictionary, type Locale } from "@/lib/i18n";
|
||||
import { getLocalizedPath, getLocalizedUrl, isComingSoonMode } from "@/lib/site";
|
||||
|
||||
type PageKey = "home" | "about" | "contact";
|
||||
|
||||
const pagePathMap: Record<PageKey, string> = {
|
||||
home: "",
|
||||
about: "/about",
|
||||
contact: "/contact",
|
||||
};
|
||||
|
||||
export function buildPageMetadata(locale: Locale, page: PageKey): Metadata {
|
||||
const dictionary = getDictionary(locale);
|
||||
const pathname = pagePathMap[page];
|
||||
const isComingSoon = isComingSoonMode();
|
||||
const metadataByPage = {
|
||||
home: {
|
||||
title: isComingSoon ? dictionary.metadata.homeTitle : dictionary.metadata.fullHomeTitle,
|
||||
description: isComingSoon ? dictionary.metadata.homeDescription : dictionary.metadata.fullHomeDescription,
|
||||
},
|
||||
about: {
|
||||
title: dictionary.metadata.aboutTitle,
|
||||
description: dictionary.metadata.aboutDescription,
|
||||
},
|
||||
contact: {
|
||||
title: dictionary.metadata.contactTitle,
|
||||
description: dictionary.metadata.contactDescription,
|
||||
},
|
||||
} as const;
|
||||
|
||||
const pageMetadata = metadataByPage[page];
|
||||
const canonicalPath = getLocalizedPath(pathname, locale);
|
||||
|
||||
return {
|
||||
title: pageMetadata.title,
|
||||
description: pageMetadata.description,
|
||||
alternates: {
|
||||
canonical: canonicalPath,
|
||||
languages: {
|
||||
ar: getLocalizedPath(pathname, "ar"),
|
||||
en: getLocalizedPath(pathname, "en"),
|
||||
"x-default": getLocalizedPath(pathname, "ar"),
|
||||
},
|
||||
},
|
||||
openGraph: {
|
||||
title: pageMetadata.title,
|
||||
description: pageMetadata.description,
|
||||
url: getLocalizedUrl(pathname, locale),
|
||||
siteName: dictionary.common.siteTitle,
|
||||
locale: locale === "ar" ? "ar_SA" : "en_US",
|
||||
type: "website",
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image",
|
||||
title: pageMetadata.title,
|
||||
description: pageMetadata.description,
|
||||
},
|
||||
};
|
||||
}
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
import type { ContactContent } from "@/content/types";
|
||||
|
||||
const FALLBACK_SITE_URL = "https://example.com";
|
||||
const SITE_MODES = ["coming-soon", "full"] as const;
|
||||
|
||||
export type SiteMode = (typeof SITE_MODES)[number];
|
||||
|
||||
function normalizeSiteUrl(value: string | undefined): string {
|
||||
const raw = value?.trim();
|
||||
|
||||
if (!raw) {
|
||||
return FALLBACK_SITE_URL;
|
||||
}
|
||||
|
||||
try {
|
||||
const url = new URL(raw);
|
||||
return url.origin;
|
||||
} catch {
|
||||
return FALLBACK_SITE_URL;
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeExternalUrl(value: string | undefined): string | undefined {
|
||||
const raw = value?.trim();
|
||||
|
||||
if (!raw) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
try {
|
||||
return new URL(raw).toString();
|
||||
} catch {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function formatDisplayValue(key: "email" | "linkedin" | "github", href: string): string {
|
||||
if (key === "email") {
|
||||
return href.replace("mailto:", "");
|
||||
}
|
||||
|
||||
const url = new URL(href);
|
||||
return `${url.hostname}${url.pathname === "/" ? "" : url.pathname.replace(/\/$/, "")}`;
|
||||
}
|
||||
|
||||
export const siteConfig = {
|
||||
ownerName: "Diyaa",
|
||||
siteUrl: normalizeSiteUrl(process.env.NEXT_PUBLIC_SITE_URL),
|
||||
email: process.env.NEXT_PUBLIC_CONTACT_EMAIL?.trim() || "",
|
||||
linkedinUrl: normalizeExternalUrl(process.env.NEXT_PUBLIC_LINKEDIN_URL),
|
||||
githubUrl: normalizeExternalUrl(process.env.NEXT_PUBLIC_GITHUB_URL),
|
||||
};
|
||||
|
||||
export function getSiteMode(): SiteMode {
|
||||
const mode = process.env.NEXT_PUBLIC_SITE_MODE?.trim();
|
||||
return SITE_MODES.includes(mode as SiteMode) ? (mode as SiteMode) : "coming-soon";
|
||||
}
|
||||
|
||||
export function isComingSoonMode(): boolean {
|
||||
return getSiteMode() === "coming-soon";
|
||||
}
|
||||
|
||||
export function getLocalizedPath(pathname: string, locale: "ar" | "en"): string {
|
||||
const normalizedPath = pathname === "/" ? "" : pathname;
|
||||
return `/${locale}${normalizedPath}`;
|
||||
}
|
||||
|
||||
export function getLocalizedUrl(pathname: string, locale: "ar" | "en"): string {
|
||||
return new URL(getLocalizedPath(pathname, locale), siteConfig.siteUrl).toString();
|
||||
}
|
||||
|
||||
export function getEmailHref(): string | undefined {
|
||||
return siteConfig.email ? `mailto:${siteConfig.email}` : undefined;
|
||||
}
|
||||
|
||||
export function getContactChannels(contact: ContactContent) {
|
||||
const valueMap = {
|
||||
email: getEmailHref(),
|
||||
linkedin: siteConfig.linkedinUrl,
|
||||
github: siteConfig.githubUrl,
|
||||
} as const;
|
||||
|
||||
return contact.channels.map((channel) => {
|
||||
const href = valueMap[channel.key];
|
||||
const external = channel.key !== "email";
|
||||
|
||||
return {
|
||||
...channel,
|
||||
href,
|
||||
external,
|
||||
value: href ? formatDisplayValue(channel.key, href) : contact.channelFallback,
|
||||
};
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user