udpate for coming soon

This commit is contained in:
diyaa
2026-03-13 03:45:13 +01:00
parent 243a182d33
commit cdf83cd466
32 changed files with 907 additions and 143 deletions
+4
View File
@@ -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";
}
+60
View File
@@ -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
View File
@@ -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,
};
});
}