SPB Git

Repository Public MIT

layout.tsx 2.3 KB 46 lines tsx

1import type { Metadata, Viewport } from "next";2import { GeistMono } from "geist/font/mono";3import { GeistSans } from "geist/font/sans";4import { headers } from "next/headers";5import { CommandPalette } from "@/components/command-palette";6import { Footer, Header } from "@/components/site";7import { t } from "@/lib/i18n";8import { getCtx } from "@/lib/session";9import { env } from "@/server/env";10import "./globals.css";1112export const metadata: Metadata = {13  metadataBase: new URL(env.publicUrl),14  title: { default: "Skills — The Open Agent Capability Registry", template: "%s · Skills" },15  description: t.statement,16  applicationName: "Skills",17  openGraph: { title: "Skills — The Open Agent Capability Registry", description: t.statement, type: "website", siteName: "Skills" },18  robots: { index: true, follow: true },19};20export const viewport: Viewport = { themeColor: "#080b10", colorScheme: "light dark", width: "device-width", initialScale: 1 };2122// Runs before first paint so the page never flashes the wrong theme. It reads one display23// preference from localStorage and nothing else; the nonce satisfies the Content-Security-Policy.24const THEME_SCRIPT = `(function(){try{var s=localStorage.getItem("skills-theme");var d=s==="dark"||(s!=="light"&&matchMedia("(prefers-color-scheme: dark)").matches);document.documentElement.dataset.theme=d?"dark":"light";var m=document.querySelector('meta[name="theme-color"]');if(m)m.setAttribute("content",d?"#080b10":"#f6f7f9");}catch(e){document.documentElement.dataset.theme="dark";}})()`;2526export default async function RootLayout({ children }: { children: React.ReactNode }) {27  // Reading the nonce opts every page into per-request rendering, which the nonce-based CSP requires.28  const nonce = (await headers()).get("x-nonce") ?? undefined;29  const ctx = await getCtx().catch(() => null);30  return (31    <html lang="en" className={`${GeistSans.variable} ${GeistMono.variable}`} suppressHydrationWarning>32      <head>33        <script nonce={nonce} dangerouslySetInnerHTML={{ __html: THEME_SCRIPT }} />34      </head>35      <body className="flex min-h-dvh flex-col">36        <Header signedIn={ctx?.principal.kind === "session"} />37        <main id="main" className="flex-1">38          {children}39        </main>40        <Footer />41        <CommandPalette />42      </body>43    </html>44  );45}46
Files main
Menu

Theme