Files
kolaytercih/src/app/layout.tsx
bilalgursen d79758adc0 perf: Lenis smooth scroll ve scroll skew efektini kaldır
Site geneli ScrollFlow sarmalayıcısı (Lenis lerp'li kaydırma + hıza bağlı
skewY) tüm sayfa katmanını her karede transform'luyor, kaydırma performansını
düşürüyordu. Yerel tarayıcı kaydırmasına dönüldü; bölüm çapaları mevcut
scroll-mt değerleriyle çalışmaya devam eder. lenis bağımlılığı ve
data-lenis-prevent işaretleri temizlendi.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-21 15:31:11 +03:00

138 lines
5.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { Metadata, Viewport } from "next";
import Script from "next/script";
import { Cal_Sans, Geist_Mono, Bricolage_Grotesque } from "next/font/google";
import localFont from "next/font/local";
import { Toaster } from "@/components/ui/sonner";
import { SiteHeader } from "@/components/site-header";
import { SiteTopBanner } from "@/components/site-top-banner";
import { ListeCekmecesiLazy } from "@/features/liste/components/liste-cekmecesi-lazy";
import { KaydetBannerLazy } from "@/features/liste/components/kaydet-banner-lazy";
import { TercihProfiliKapisiLazy } from "@/features/liste/components/tercih-profili-kapisi-lazy";
import { HeaderGate } from "@/components/header-gate";
import { ProgressiveBlur } from "@/components/ui/skiper-ui/skiper41";
import { DevPanelMount } from "@/components/dev/dev-panel-mount";
import { JsonLd, organizationJsonLd, webSiteJsonLd, SITE_URL } from "@/lib/seo";
import "./globals.css";
const calSans = Cal_Sans({
variable: "--font-cal-sans",
weight: "400",
subsets: ["latin", "latin-ext"],
});
const clarityCity = localFont({
variable: "--font-clarity-city",
src: [
{ path: "../fonts/ClarityCity-Regular.woff2", weight: "400" },
{ path: "../fonts/ClarityCity-Medium.woff2", weight: "500" },
{ path: "../fonts/ClarityCity-SemiBold.woff2", weight: "600" },
{ path: "../fonts/ClarityCity-Bold.woff2", weight: "700" },
{ path: "../fonts/ClarityCity-ExtraBold.woff2", weight: "800" },
],
});
const geistMono = Geist_Mono({
variable: "--font-geist-mono",
subsets: ["latin"],
// Yalnızca markdown/kod bloklarında kullanılıyor; landing'de preload israfı
preload: false,
});
const bricolage = Bricolage_Grotesque({
variable: "--font-bricolage-grotesque",
subsets: ["latin", "latin-ext"],
axes: ["opsz"],
});
export const metadata: Metadata = {
metadataBase: new URL(SITE_URL),
title: {
default: "KolayTercih — Yapay Zekâ Destekli YKS Tercih Danışmanı",
template: "%s — KolayTercih",
},
description:
"YKS sıralamana göre gerçek YÖK Atlas verisiyle dengeli 24 tercihlik liste. İnsan danışmandan çok daha düşük fiyata, yapay zekâ destekli tercih danışmanlığı.",
applicationName: "KolayTercih",
openGraph: {
type: "website",
locale: "tr_TR",
siteName: "KolayTercih",
url: "/",
title: "KolayTercih — Yapay Zekâ Destekli YKS Tercih Danışmanı",
description:
"YKS sıralamana göre gerçek YÖK Atlas verisiyle dengeli 24 tercihlik liste. Yapay zekâ destekli tercih danışmanlığı.",
},
twitter: { card: "summary_large_image" },
robots: { index: true, follow: true },
};
export const viewport: Viewport = {
themeColor: "#f8fafc",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html
lang="tr"
// `h-full` verme: html auto yükseklikte içerikle büyür, viewport tabanı
// body'deki min-h-dvh'den gelir.
className={`${calSans.variable} ${clarityCity.variable} ${geistMono.variable} ${bricolage.variable} antialiased`}
>
<body className="min-h-dvh flex flex-col bg-slate-50">
<HeaderGate>
{/* Site geneli progressive blur — üst ve alt */}
<div className="pointer-events-none fixed inset-x-0 top-0 z-40 h-28 print:hidden">
<ProgressiveBlur
position="top"
backgroundColor="#f8fafc"
height="112px"
blurAmount="6px"
/>
</div>
<div className="pointer-events-none fixed inset-x-0 bottom-0 z-40 h-28 print:hidden">
<ProgressiveBlur
position="bottom"
backgroundColor="#f8fafc"
height="112px"
blurAmount="6px"
/>
</div>
<SiteTopBanner />
<SiteHeader />
</HeaderGate>
<div className="flex min-h-0 flex-1 flex-col pb-28 print:pb-0">
{children}
</div>
{/* Manuel 24'lük liste çekmecesi + "+" uçuş katmanı (navbar'dan açılır) */}
<ListeCekmecesiLazy />
{/* Girişsiz + 3 seçimli kullanıcıya "listen yalnızca bu tarayıcıda" banner'ı */}
<KaydetBannerLazy />
{/* İlk "+" için sıra + sihirbaz kapısı */}
<TercihProfiliKapisiLazy />
<Toaster position="top-center" />
{/* Dev süperadmin paneli — prod build'de modül grafiğine bile girmez */}
{process.env.NODE_ENV !== "production" ? <DevPanelMount /> : null}
<JsonLd data={organizationJsonLd()} />
<JsonLd data={webSiteJsonLd()} />
{/* Rybbit analitik — afterInteractive: hydration sonrası client'ta
enjekte edilir, LCP/kritik yolla yarışmaz. Yalnızca prod build'de:
Rybbit localhost'u da takip ettiği için dev trafiği prod verisini
kirletmesin (DevPanel ile aynı kapı). mask-patterns: /sonuc URL'i
ham başarı sıralamasını, /odeme/sonuc sipariş kimliğini taşıyor. */}
{process.env.NODE_ENV === "production" ? (
<Script
src="https://rybbit.kolaytercih.com/api/script.js"
data-site-id="f2cb042c657e"
data-mask-patterns='["/sonuc", "/odeme/sonuc"]'
strategy="afterInteractive"
/>
) : null}
</body>
</html>
);
}