Files
hadlock.tech/src/app/layout.tsx
T
soconnor d0ffd7dc04 Add theme system, project banners, mobile nav, and hero logo
- System-first theming via light-dark() with explicit .light/.dark overrides
- Project banners: Racetix, beenvoice, RaceHub, HRIStudio
- Mobile navigation with portaled blur backdrop
- Hero logo placement and page copy polish
- Remove tRPC, migrate contact flow to direct API route
2026-08-02 02:40:27 -04:00

121 lines
3.0 KiB
TypeScript

import "~/styles/globals.css";
import { type Metadata } from "next";
import {
Geist,
Geist_Mono,
Inter,
Playfair_Display,
Rajdhani,
Titillium_Web,
} from "next/font/google";
import Script from "next/script";
import { env } from "~/env";
export const metadata: Metadata = {
metadataBase: new URL("https://hadlock.tech"),
title: {
default: "Hadlock Technologies — Everything technical, handled",
template: "%s · Hadlock Technologies",
},
description:
"Hadlock Technologies runs networks, servers, cloud systems, databases, web applications, and commerce. One accountable name covers everything from infrastructure to applications.",
keywords: [
"IT consulting",
"UniFi",
"network infrastructure",
"cloud servers",
"web development",
"Shopify",
"Long Island",
"New York",
"Hadlock Technologies",
],
authors: [{ name: "Hadlock Technologies LLC" }],
openGraph: {
title: "Hadlock Technologies — Everything technical, handled",
description:
"One accountable technical partner for networks, servers, cloud, databases, web, and commerce.",
url: "https://hadlock.tech",
siteName: "Hadlock Technologies",
type: "website",
},
};
const umamiEnabled =
!!env.NEXT_PUBLIC_UMAMI_SRC && !!env.NEXT_PUBLIC_UMAMI_WEBSITE_ID;
const themeScript = `
try {
const theme = localStorage.getItem("hadlock_theme");
if (theme === "light") {
document.documentElement.classList.add("light");
} else if (theme === "dark") {
document.documentElement.classList.add("dark");
}
} catch {}
`;
const geist = Geist({
variable: "--font-geist-sans",
subsets: ["latin"],
});
const geistMono = Geist_Mono({
subsets: ["latin"],
variable: "--font-geist-mono",
});
const playfair = Playfair_Display({
variable: "--font-playfair",
subsets: ["latin"],
weight: ["400", "500", "600", "700"],
});
const rajdhani = Rajdhani({
variable: "--font-rajdhani",
subsets: ["latin"],
weight: ["400", "500", "600", "700"],
});
const titillium = Titillium_Web({
variable: "--font-titillium",
subsets: ["latin"],
weight: ["400", "600", "700"],
});
const inter = Inter({
variable: "--font-inter",
subsets: ["latin"],
weight: ["400", "500", "600", "700"],
});
export default function RootLayout({
children,
}: Readonly<{ children: React.ReactNode }>) {
return (
<html
lang="en"
suppressHydrationWarning
className={`${geist.variable} ${geistMono.variable} ${playfair.variable} ${rajdhani.variable} ${titillium.variable} ${inter.variable}`}
>
<body className="font-sans">
<Script
id="hadlock-theme"
strategy="beforeInteractive"
dangerouslySetInnerHTML={{ __html: themeScript }}
/>
{children}
{umamiEnabled && (
<Script
src={env.NEXT_PUBLIC_UMAMI_SRC}
data-website-id={env.NEXT_PUBLIC_UMAMI_WEBSITE_ID}
strategy="afterInteractive"
/>
)}
</body>
</html>
);
}