TypeScript 55.4%
Python 43.2%
SQL 1.2%
1import type { Metadata, Viewport } from "next";2import { Inter, JetBrains_Mono } from "next/font/google";3import type { ReactNode } from "react";4import { CommandPalette } from "@/components/command-palette";5import { EventDrawerProvider } from "@/components/event-drawer";6import { Footer } from "@/components/footer";7import { MobileNav, TopNav } from "@/components/nav";8import { PrefsProvider } from "@/components/prefs";9import { Providers } from "@/components/theme";10import { SITE_URL } from "@/lib/api";11import "./globals.css";1213const inter = Inter({ subsets: ["latin"], variable: "--font-inter", display: "swap" });14const mono = JetBrains_Mono({ subsets: ["latin"], variable: "--font-jetbrains", display: "swap" });1516export const metadata: Metadata = {17 metadataBase: new URL(SITE_URL),18 title: { default: "WebSensor — The Web is changing. We are watching.", template: "%s · WebSensor" },19 description: "WebSensor continuously watches the public web for meaningful changes, preserving evidence and connecting signals into real-world events.",20 applicationName: "WebSensor",21 authors: [{ name: "Simon-Pierre Boucher", url: "https://www.maclustr.io" }],22 creator: "Simon-Pierre Boucher",23 openGraph: { type: "website", siteName: "WebSensor", url: SITE_URL, title: "WebSensor — The Web is changing. We are watching.", description: "Real-time Internet change intelligence: what changed, where, when, whether it was silent, how important it is — with immutable evidence." },24 twitter: { card: "summary_large_image", title: "WebSensor — The Web is changing. We are watching.", description: "Detect what changed. Know why it matters." },25 alternates: { canonical: "/", types: { "application/rss+xml": `${SITE_URL}/api/v1/feed.rss` } },26 robots: { index: true, follow: true },27};2829export const viewport: Viewport = { themeColor: [{ media: "(prefers-color-scheme: dark)", color: "#0a0e15" }, { media: "(prefers-color-scheme: light)", color: "#f6f7fa" }], width: "device-width", initialScale: 1, viewportFit: "cover" };3031export default function RootLayout({ children }: { children: ReactNode }) {32 return (33 <html lang="en" className={`${inter.variable} ${mono.variable} dark`} suppressHydrationWarning>34 <body className="min-h-dvh">35 <Providers>36 <PrefsProvider>37 <EventDrawerProvider>38 <a href="#main" className="sr-only focus:not-sr-only focus:fixed focus:left-2 focus:top-2 focus:z-[70] focus:rounded-md focus:bg-panel focus:px-3 focus:py-2">Skip to content</a>39 <TopNav />40 <main id="main" className="mx-auto w-full max-w-[1600px] px-3 py-4 pb-24 sm:px-4 lg:pb-6">{children}</main>41 <Footer />42 <MobileNav />43 <CommandPalette />44 </EventDrawerProvider>45 </PrefsProvider>46 </Providers>47 </body>48 </html>49 );50}51