82 lines
3.0 KiB
TypeScript
82 lines
3.0 KiB
TypeScript
import type { Metadata, Viewport } from "next";
|
|
import localFont from "next/font/local";
|
|
import Script from "next/script";
|
|
import { Toaster } from "@/components/ui/sonner";
|
|
import { StaleBuildGuard } from "@/components/stale-build-guard";
|
|
import { StaleClientRecovery } from "@/components/stale-client-recovery";
|
|
import { ViewportScrollLock } from "@/components/viewport-scroll-lock";
|
|
import { themePreferenceBootScript } from "@/lib/theme-preference";
|
|
|
|
// Vendored Inter latin variable (OFL). Do not switch back to next/font/google;
|
|
// the publish image cannot download fonts at build time.
|
|
const inter = localFont({
|
|
src: "./fonts/InterVariable-latin.woff2",
|
|
display: "swap",
|
|
variable: "--font-inter",
|
|
weight: "100 900",
|
|
});
|
|
|
|
// Vendored 9-glyph Noto Sans Symbols subset (OFL) — ☉ ☽ ☿ ♀ ♂ ♃ ♄ ☊ ☋, 1.5 KB.
|
|
// The North Indian chart draws planets as these symbols, so the face has to be
|
|
// present rather than hoped for: Apple Symbols / Segoe UI Symbol cover the set
|
|
// on their own platforms, Android and most Linux browsers do not.
|
|
// `adjustFontFallback: false` on purpose: the synthetic Arial-metric fallback
|
|
// next/font/local would otherwise inject carries its own ♀ ♂ and would swallow
|
|
// the rest of the stack for the glyphs it cannot draw.
|
|
const planetGlyphs = localFont({
|
|
src: "./fonts/NotoSansSymbols-planets.woff2",
|
|
display: "swap",
|
|
variable: "--font-planet-glyphs",
|
|
weight: "400",
|
|
style: "normal",
|
|
adjustFontFallback: false,
|
|
});
|
|
|
|
export const metadata: Metadata = {
|
|
title: "Jyotisha · 印度占星",
|
|
description: "与 Mastra Agent 对话,基于星盘证据讨论事业、关系与时间窗口。",
|
|
};
|
|
|
|
export const viewport: Viewport = {
|
|
width: "device-width",
|
|
initialScale: 1,
|
|
viewportFit: "cover",
|
|
interactiveWidget: "resizes-content",
|
|
};
|
|
|
|
export default function RootLayout({ children }: Readonly<{ children: React.ReactNode }>) {
|
|
const enableReactDevTools = process.env.NODE_ENV === "development"
|
|
&& process.env.NEXT_PUBLIC_ENABLE_REACT_DEVTOOLS === "1";
|
|
|
|
return (
|
|
<html lang="zh-CN" className={`${inter.variable} ${planetGlyphs.variable}`} suppressHydrationWarning>
|
|
<head>
|
|
{/* Synchronous on purpose: a pinned theme must be on <html> before the
|
|
first paint, or the page flashes the other theme on every load. */}
|
|
<script dangerouslySetInnerHTML={{ __html: themePreferenceBootScript }} />
|
|
{enableReactDevTools && (
|
|
<>
|
|
<Script
|
|
crossOrigin="anonymous"
|
|
src="https://unpkg.com/react-grab/dist/index.global.js"
|
|
strategy="lazyOnload"
|
|
/>
|
|
<Script
|
|
crossOrigin="anonymous"
|
|
src="https://unpkg.com/react-scan/dist/auto.global.js"
|
|
strategy="lazyOnload"
|
|
/>
|
|
</>
|
|
)}
|
|
</head>
|
|
<body>
|
|
<StaleClientRecovery />
|
|
<ViewportScrollLock />
|
|
<StaleBuildGuard />
|
|
{children}
|
|
<Toaster />
|
|
</body>
|
|
</html>
|
|
);
|
|
}
|