97 lines
2.7 KiB
TypeScript
97 lines
2.7 KiB
TypeScript
import type { Metadata, Viewport } from 'next';
|
|
import localFont from 'next/font/local';
|
|
import { dict } from '@/lib/i18n/dictionaries';
|
|
import './globals.css';
|
|
|
|
/**
|
|
* Fonts are self-hosted (woff2 in ./fonts) rather than fetched from Google
|
|
* at build time — Google Fonts is unreliable behind some networks, which is
|
|
* why the Persian face previously failed to load. All files ship in-repo.
|
|
*
|
|
* Vazirmatn is split into Arabic + Latin subsets. We expose each as its own
|
|
* CSS variable and chain them in the font stacks (Arabic first), so Persian
|
|
* glyphs resolve from the Arabic file and Latin characters fall through to
|
|
* the Latin file via normal font-family fallback.
|
|
*/
|
|
const vazirmatnArabic = localFont({
|
|
src: './fonts/Vazirmatn-Arabic.woff2',
|
|
weight: '100 900',
|
|
style: 'normal',
|
|
display: 'swap',
|
|
variable: '--font-vaz-ar',
|
|
// Cover the Arabic/Persian block so the browser knows to use this face.
|
|
declarations: [{ prop: 'unicode-range', value: 'U+0600-06FF, U+0750-077F, U+08A0-08FF, U+FB50-FDFF, U+FE70-FEFF, U+200C-200D' }],
|
|
});
|
|
|
|
const vazirmatnLatin = localFont({
|
|
src: './fonts/Vazirmatn-Latin.woff2',
|
|
weight: '100 900',
|
|
style: 'normal',
|
|
display: 'swap',
|
|
variable: '--font-vaz-lat',
|
|
});
|
|
|
|
const syne = localFont({
|
|
src: './fonts/Syne-Variable.woff2',
|
|
weight: '400 800',
|
|
style: 'normal',
|
|
display: 'swap',
|
|
variable: '--font-syne',
|
|
});
|
|
|
|
const spaceMono = localFont({
|
|
src: [
|
|
{ path: './fonts/SpaceMono-Regular.woff2', weight: '400', style: 'normal' },
|
|
{ path: './fonts/SpaceMono-Bold.woff2', weight: '700', style: 'normal' },
|
|
],
|
|
display: 'swap',
|
|
variable: '--font-space-mono',
|
|
});
|
|
|
|
export const viewport: Viewport = {
|
|
themeColor: '#020510',
|
|
width: 'device-width',
|
|
initialScale: 1,
|
|
};
|
|
|
|
export const metadata: Metadata = {
|
|
metadataBase: new URL('https://soroushasadi.ir'),
|
|
title: {
|
|
default: dict.fa.meta.title,
|
|
template: '%s — Soroush Asadi',
|
|
},
|
|
description: dict.fa.meta.description,
|
|
alternates: {
|
|
canonical: '/',
|
|
languages: {
|
|
'fa-IR': '/',
|
|
'en-US': '/',
|
|
},
|
|
},
|
|
openGraph: {
|
|
type: 'website',
|
|
title: dict.fa.meta.title,
|
|
description: dict.fa.meta.description,
|
|
siteName: 'Soroush Asadi',
|
|
images: ['/avatar.svg'],
|
|
},
|
|
twitter: {
|
|
card: 'summary_large_image',
|
|
title: dict.en.meta.title,
|
|
description: dict.en.meta.description,
|
|
images: ['/avatar.svg'],
|
|
},
|
|
};
|
|
|
|
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
return (
|
|
<html lang="fa" dir="rtl" suppressHydrationWarning>
|
|
<body
|
|
className={`${vazirmatnArabic.variable} ${vazirmatnLatin.variable} ${syne.variable} ${spaceMono.variable} min-h-screen bg-base text-slate-200 antialiased`}
|
|
>
|
|
{children}
|
|
</body>
|
|
</html>
|
|
);
|
|
}
|