SPB Git forge

spb/cancerindex

Public
37commits 1branches 0releases
2.9 MBsize
maindefault branch
10 days agolast push
TypeScript 97.2% SQL 1.5% CSS 0.6% JavaScript 0.5%
2.7 KB · 55 lines tsx
Raw Blame History
1import type { Metadata, Viewport } from 'next';2import { Newsreader, Inter, IBM_Plex_Mono } from 'next/font/google';3import './globals.css';4import { SiteHeader } from '@/components/layout/site-header';5import { SiteFooter } from '@/components/layout/site-footer';6import { SITE_URL, SITE_NAME, TAGLINE, AUTHOR_NAME, AUTHOR_URL } from '@/lib/site';78const display = Newsreader({ variable: '--font-display', subsets: ['latin'], display: 'swap', weight: ['400', '500', '600'], style: ['normal', 'italic'] });9const ui = Inter({ variable: '--font-ui', subsets: ['latin'], display: 'swap' });10const code = IBM_Plex_Mono({ variable: '--font-code', subsets: ['latin'], display: 'swap', weight: ['400', '500'] });1112export const metadata: Metadata = {13  metadataBase: new URL(SITE_URL),14  title: { default: `${SITE_NAME} — ${TAGLINE}`, template: `%s · ${SITE_NAME}` },15  description: 'A provenance-first index of every recognized cancer entity: taxonomy, epidemiology, genomics, variants, therapies, clinical trials, literature and transparent rankings.',16  applicationName: SITE_NAME,17  authors: [{ name: AUTHOR_NAME, url: AUTHOR_URL }],18  creator: AUTHOR_NAME,19  robots: { index: true, follow: true },20  openGraph: { type: 'website', siteName: SITE_NAME, url: SITE_URL, title: `${SITE_NAME} — ${TAGLINE}`, description: 'Provenance-first oncology intelligence: every number linked to its source.' },21  twitter: { card: 'summary_large_image', title: SITE_NAME, description: TAGLINE, creator: '@spboucher' },22};2324export const viewport: Viewport = {25  width: 'device-width',26  initialScale: 1,27  themeColor: [28    { media: '(prefers-color-scheme: light)', color: '#fafaf7' },29    { media: '(prefers-color-scheme: dark)', color: '#151514' },30  ],31};3233/** Applies the stored theme before first paint (no flash); "system" = no attribute. */34const THEME_BOOT = `try{var t=localStorage.getItem('ci-theme');if(t==='dark'||t==='light'){document.documentElement.setAttribute('data-theme',t)}}catch(e){}`;3536export default function RootLayout({ children }: { children: React.ReactNode }) {37  return (38    <html lang="en" className={`${display.variable} ${ui.variable} ${code.variable} h-full antialiased`} suppressHydrationWarning>39      <head>40        <script dangerouslySetInnerHTML={{ __html: THEME_BOOT }} />41      </head>42      <body className="flex min-h-full flex-col">43        <a href="#main" className="sr-only focus:not-sr-only focus:fixed focus:left-3 focus:top-3 focus:z-[200] focus:border focus:border-accent focus:bg-paper focus:px-3 focus:py-2 focus:text-sm">44          Skip to content45        </a>46        <SiteHeader />47        <main id="main" className="mx-auto w-full max-w-[1400px] flex-1 px-4 sm:px-6">48          {children}49        </main>50        <SiteFooter />51      </body>52    </html>53  );54}55