Files
kolaytercih/src/app/layout.tsx
bilalgursen 26626ae449 feat(easter-egg): footer'da Tâhâ 25–26 âyeti, konsolda piksel kum saati + Asr Sûresi
- Footer: "Rabbi'şrah lî sadrî ve yessir lî emrî" (Tâhâ 25–26) Arapça +
  Diyanet İşleri meali; Arapça Amiri Quran ile (önceden yüklenmez, ~45 KB).
  Altında PixelMark'lı kaynak satırı.
- Konsol: ConsoleAsr artık kök layout'ta. Logodaki renklerle dot-matrix kum
  saati, Asr Sûresi (Diyanet mushafı + Diyanet meali, kaynakla bayt bayt
  aynı), İmam Şâfiî'nin sûfîlerden aktardığı vakit sözü, /meraklisina linki.
  Tarayıcı boşa çıkınca bir kez basar.
- DESIGN.md §3: Arapça yazı tipinin tek işi (yalnız Kur'an metni) yazıldı.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 19:27:08 +03:00

144 lines
5.9 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 { DevPanelMount } from "@/components/dev/dev-panel-mount";
import { ConsoleAsr } from "@/components/console-asr";
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",
alternates: {
types: { "application/rss+xml": "/feed.xml" },
},
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">
{/* Klavyeyle gelen için ilk durak: üst bandı ve menüyü atla
(WCAG 2.4.1). Odaklanınca görünür, sitenin hap ölçüsünde. */}
<a
href="#icerik"
className="sr-only focus:not-sr-only focus:fixed focus:top-3 focus:left-3 focus:z-[60] focus:inline-flex focus:h-11 focus:items-center focus:rounded-full focus:border focus:border-slate-200 focus:bg-white focus:px-4 focus:text-sm focus:font-semibold focus:text-slate-900 focus:shadow-lg focus:outline-none focus-visible:ring-3 focus-visible:ring-ring/50"
>
İçeriğe geç
</a>
<HeaderGate>
{/* Site geneli progressive blur — üst ve alt. Stil globals.css'te
(.kt-sayfa-blur): iOS/iPadOS'ta fixed + backdrop-filter katmanı
kaydırmada ekranın ortasına kayıyor, orada bulanıklık @supports
ile düşürülüp degrade fade korunuyor. */}
<div className="kt-sayfa-blur kt-sayfa-blur-ust print:hidden" aria-hidden />
<div className="kt-sayfa-blur kt-sayfa-blur-alt print:hidden" aria-hidden />
<SiteTopBanner />
<SiteHeader />
</HeaderGate>
<div
id="icerik"
tabIndex={-1}
className="flex min-h-0 flex-1 flex-col pb-28 outline-none 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" />
{/* DevTools'u açan meraklıya piksel kum saati + Asr Sûresi */}
<ConsoleAsr />
{/* 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>
);
}