- Remove external next-view-transitions dependency - Use Next.js 16 native navigation and Safari 18+ native View Transition API - Add ViewTransitionProvider for minimal wrapping with Safari 18+ detection - Updated all Link imports from external package to next/link - Removed link-wrapper.tsx and view-transitions-wrapper.tsx This resolves Safari compatibility issues while maintaining transitions on modern browsers.
166 lines
4.5 KiB
TypeScript
166 lines
4.5 KiB
TypeScript
import '../styles/globals.css';
|
|
import type { Metadata } from 'next';
|
|
import { siteConfig } from '@/lib/config';
|
|
import { getAllPostsSorted } from '@/lib/posts';
|
|
import { LayoutShell } from '@/components/layout-shell';
|
|
import { ThemeProvider } from 'next-themes';
|
|
import { Playfair_Display, LXGW_WenKai_TC } from 'next/font/google';
|
|
import { JsonLd } from '@/components/json-ld';
|
|
import { WebVitals } from '@/components/web-vitals';
|
|
import { ViewTransitionProvider } from '@/components/view-transition-provider';
|
|
import NextTopLoader from 'nextjs-toploader';
|
|
|
|
const playfair = Playfair_Display({
|
|
subsets: ['latin'],
|
|
variable: '--font-serif-eng',
|
|
display: 'swap',
|
|
});
|
|
|
|
const lxgwWenKai = LXGW_WenKai_TC({
|
|
weight: ['400', '700'],
|
|
subsets: ['latin'],
|
|
variable: '--font-serif-cn',
|
|
display: 'swap',
|
|
preload: true,
|
|
adjustFontFallback: false,
|
|
});
|
|
|
|
export const metadata: Metadata = {
|
|
title: {
|
|
default: siteConfig.title,
|
|
template: `%s | ${siteConfig.title}`
|
|
},
|
|
description: siteConfig.description,
|
|
metadataBase: new URL(siteConfig.url),
|
|
creator: siteConfig.author,
|
|
robots: {
|
|
index: true,
|
|
follow: true,
|
|
googleBot: {
|
|
index: true,
|
|
follow: true,
|
|
'max-video-preview': -1,
|
|
'max-image-preview': 'large',
|
|
'max-snippet': -1
|
|
}
|
|
},
|
|
openGraph: {
|
|
type: 'website',
|
|
title: siteConfig.title,
|
|
description: siteConfig.description,
|
|
url: siteConfig.url,
|
|
siteName: siteConfig.title,
|
|
locale: siteConfig.defaultLocale,
|
|
images: [
|
|
{
|
|
url: siteConfig.ogImage,
|
|
width: 1200,
|
|
height: 630,
|
|
alt: siteConfig.title
|
|
}
|
|
]
|
|
},
|
|
twitter: {
|
|
card: siteConfig.twitterCard,
|
|
creator: siteConfig.social.twitter || undefined,
|
|
title: siteConfig.title,
|
|
description: siteConfig.description,
|
|
images: [siteConfig.ogImage]
|
|
},
|
|
icons: {
|
|
icon: '/favicon.png',
|
|
apple: '/favicon.png'
|
|
},
|
|
alternates: {
|
|
types: {
|
|
'application/rss+xml': `${siteConfig.url}/feed.xml`
|
|
}
|
|
}
|
|
};
|
|
|
|
export default async function RootLayout({
|
|
children
|
|
}: {
|
|
children: React.ReactNode;
|
|
}) {
|
|
const theme = siteConfig.theme;
|
|
const recentPosts = getAllPostsSorted()
|
|
.slice(0, 5)
|
|
.map((p) => ({ title: p.title, url: p.url }));
|
|
|
|
const websiteSchema = {
|
|
'@context': 'https://schema.org',
|
|
'@type': 'WebSite',
|
|
name: siteConfig.title,
|
|
description: siteConfig.description,
|
|
url: siteConfig.url,
|
|
inLanguage: siteConfig.defaultLocale,
|
|
author: {
|
|
'@type': 'Person',
|
|
name: siteConfig.author,
|
|
url: siteConfig.url,
|
|
},
|
|
potentialAction: {
|
|
'@type': 'SearchAction',
|
|
target: {
|
|
'@type': 'EntryPoint',
|
|
urlTemplate: `${siteConfig.url}/blog?search={search_term_string}`,
|
|
},
|
|
'query-input': 'required name=search_term_string',
|
|
},
|
|
};
|
|
|
|
const organizationSchema = {
|
|
'@context': 'https://schema.org',
|
|
'@type': 'Organization',
|
|
name: siteConfig.name,
|
|
url: siteConfig.url,
|
|
logo: `${siteConfig.url}${siteConfig.avatar}`,
|
|
sameAs: [
|
|
siteConfig.social.github,
|
|
siteConfig.social.twitter && `https://twitter.com/${siteConfig.social.twitter.replace('@', '')}`,
|
|
siteConfig.social.mastodon,
|
|
].filter(Boolean),
|
|
};
|
|
|
|
|
|
|
|
return (
|
|
<html lang={siteConfig.defaultLocale} suppressHydrationWarning className={`${playfair.variable} ${lxgwWenKai.variable}`}>
|
|
<head>
|
|
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="anonymous" />
|
|
</head>
|
|
<body>
|
|
<NextTopLoader
|
|
color={theme.accent}
|
|
height={3}
|
|
showSpinner={false}
|
|
speed={200}
|
|
shadow={`0 0 10px ${theme.accent}, 0 0 5px ${theme.accent}`}
|
|
/>
|
|
<JsonLd data={websiteSchema} />
|
|
<JsonLd data={organizationSchema} />
|
|
<style
|
|
dangerouslySetInnerHTML={{
|
|
__html: `
|
|
:root {
|
|
--color-accent: ${theme.accent};
|
|
--color-accent-soft: ${theme.accentSoft};
|
|
--color-accent-text-light: ${theme.accentTextLight};
|
|
--color-accent-text-dark: ${theme.accentTextDark};
|
|
}
|
|
`
|
|
}}
|
|
/>
|
|
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
|
|
<ViewTransitionProvider>
|
|
<LayoutShell recentPosts={recentPosts}>{children}</LayoutShell>
|
|
</ViewTransitionProvider>
|
|
</ThemeProvider>
|
|
<WebVitals />
|
|
</body>
|
|
</html>
|
|
);
|
|
}
|