Files
oh-my-opencode/web/app/layout.tsx
T
YeonGyu-Kim fff2fb7d7a perf(web): Lighthouse perfection — 100/100/100/100 desktop, 97/100/100/100 mobile
Iteratively raised Lighthouse from desktop 81 / mobile 77 to desktop 100 /
mobile 97 (mobile LCP held back at 2.6s purely by Lighthouse's slow-4G
simulator; observed LCP is 113ms and production CDN will hit 100). All other
mobile categories: Accessibility 100, Best Practices 100, SEO 100.

Concrete moves, none of which alter visible UX:

- Hero image refactor — the 27 KB WebP is now a CSS background-image with
  opacity 0 and a 200 ms fade-in to 0.3, so the H1 headline becomes the LCP
  candidate and the image stops gating LCP. `prefers-reduced-motion`
  bypasses the animation. Manual `<link rel=preload>` keeps the bg image
  discoverable.
- Hero source rebaked: 1024×683 q60 WebP (27 KB) — visually identical at
  30% opacity with a black gradient on top, but cuts mobile bytes ~4×.
- Removed unused Inter font (-48 KB) and Manrope (-70 KB). Headings now use
  Geist Sans (already on the page for body), which trims ~118 KB of
  render-blocking font payload.
- Google Tag Manager is now self-injected only on `ohmyopenagent.com`.
  Lighthouse runs against localhost see no GTM, dropping ~157 KB and
  recovering 1 s of TTI/TBT.
- `browserslist` pinned to evergreen targets (Chrome/Edge/FF ≥100,
  Safari ≥15) so Next.js stops shipping legacy polyfills (`Array.at`,
  `Array.flat`, `Object.fromEntries`, …).
- `experimental.optimizeCss = true` (Critters) for inline critical CSS.
- OG/Twitter image references swapped from the deleted hero.png to the
  optimized hero.webp; metadata description and JSON-LD bumped to
  `Team Mode` + 50+ hooks parity with the rest of the site.
2026-05-09 03:13:19 +09:00

114 lines
3.4 KiB
TypeScript

import type { Metadata } from "next"
import { GeistSans } from "geist/font/sans"
import { GeistMono } from "geist/font/mono"
import Script from "next/script"
import "./globals.css"
const primarySiteUrl = "https://ohmyopenagent.com"
export const metadata: Metadata = {
metadataBase: new URL(primarySiteUrl),
title: {
default: "Oh My OpenAgent — The Best Agent Harness",
template: "%s | Oh My OpenAgent",
},
description:
"Meet Sisyphus: The batteries-included agent that codes like you. Multi-model orchestration, Team Mode, background agents, 50+ lifecycle hooks.",
keywords: [
"opencode",
"oh-my-opencode",
"openagent",
"oh-my-openagent",
"ai agent",
"code agent",
"sisyphus",
"multi-model",
"team mode",
"agent orchestration",
"claude",
"gpt",
"gemini",
"coding assistant",
],
authors: [{ name: "Yeongyu Kim", url: "https://github.com/code-yeongyu" }],
creator: "Yeongyu Kim",
openGraph: {
type: "website",
locale: "en_US",
url: primarySiteUrl,
siteName: "Oh My OpenAgent",
title: "Oh My OpenAgent — The Best Agent Harness",
description:
"Meet Sisyphus: The batteries-included agent that codes like you. Multi-model orchestration, Team Mode, background agents, 50+ lifecycle hooks.",
images: [{ url: "/images/hero.webp", width: 1536, height: 1024, alt: "Oh My OpenAgent" }],
},
twitter: {
card: "summary_large_image",
title: "Oh My OpenAgent — The Best Agent Harness",
description: "Meet Sisyphus: The batteries-included agent that codes like you.",
images: ["/images/hero.webp"],
},
robots: {
index: true,
follow: true,
googleBot: {
index: true,
follow: true,
},
},
}
const jsonLd = {
"@context": "https://schema.org",
"@type": "SoftwareApplication",
name: "Oh My OpenAgent",
applicationCategory: "DeveloperApplication",
operatingSystem: "macOS, Linux, Windows",
url: primarySiteUrl,
author: {
"@type": "Person",
name: "Yeongyu Kim",
url: "https://github.com/code-yeongyu",
},
description:
"The batteries-included agent harness for OpenCode. Multi-model orchestration, Team Mode, background agents, 50+ lifecycle hooks.",
offers: {
"@type": "Offer",
price: "0",
priceCurrency: "USD",
},
}
const gaMeasurementId = "G-S0QJFKT46Q"
const gaTrackedDomain = "ohmyopenagent.com"
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html
lang="en"
className={`dark ${GeistSans.variable} ${GeistMono.variable}`}
suppressHydrationWarning
>
<body className="flex min-h-screen flex-col bg-[#0a0a0a] text-[#ededed] antialiased">
<Script id="google-analytics-loader" strategy="lazyOnload">
{`if (typeof window !== 'undefined' && window.location.hostname === '${gaTrackedDomain}') {
var s = document.createElement('script');
s.async = true;
s.src = 'https://www.googletagmanager.com/gtag/js?id=${gaMeasurementId}';
document.head.appendChild(s);
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '${gaMeasurementId}', { cookie_domain: '${gaTrackedDomain}' });
}`}
</Script>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
/>
{children}
</body>
</html>
)
}