Files
kolaytercih/src/app/layout.tsx
bilalgursen 004473a078 chore(metin): danışman fiyat kıyası rakamsız ve atıfsız [Bilal onayı gerekir]
52520ac'nin ALTERNATİFİ (ikisi birlikte alınmaz). Canlıdaki "2.000–10.000
TL / onda bir" de, 52520ac'deki "1.000–5.000 TL — Armut, 2026" da teyitsiz;
bu commit TL aralığını, üçüncü taraf atfını ve "onda bir" oranını kaldırır:
- page.tsx sorun kartı: "…danışmanının ücreti birkaç bin lirayı bulabiliyor."
- page.tsx kıyas tablosu Fiyat/İnsan danışman: "Danışmana göre değişir"
- page.tsx fiyat bölümü: "İnsan danışmanın birkaç bin liraya yaptığı işi…"
- paket/page.tsx başlık: "onda bir fiyatına" → "çok daha düşük fiyata";
  alt metin: "…ücreti bu dönemde birkaç bin lirayı bulabiliyor."
- layout.tsx description: "İnsan danışmandan çok daha düşük fiyata, …"
Hero'daki yorum içi ölü <p> bloğuna dokunulmadı (9d450c5 ile çakışmasın).
Reddedilirse: git merge gece/p3b-tadimlik-dili~1

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

141 lines
5.5 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 { ScrollFlow } from "@/components/scroll-flow";
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 — Lenis içerik yüksekliğini <html>'e bağlı ResizeObserver
// ile izliyor; html sabit %100 kalınca lazy yüklenen içerik sonrası limit
// bayatlıyor ve sayfa sonunda scroll kilitleniyor. html auto yükseklikte
// içerikle büyümeli, 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>
<ScrollFlow className="flex min-h-0 flex-1 flex-col pb-28 print:pb-0">
{children}
</ScrollFlow>
{/* 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>
);
}