Files
kolaytercih/src/app/layout.tsx
bilalgursen e62c6f07df
Some checks failed
Deploy / deploy (push) Failing after 1h28m6s
Update package.json scripts, enhance layout with new components, and improve API error handling
- Added new scripts for database operations and temporary production in package.json.
- Integrated KaydetBannerLazy component into the layout for improved user notifications.
- Enhanced API error handling in the soru route to mark credit exhaustion.
- Updated the IletisimPage for better button styling and user experience.
- Refactored ListemPage to streamline user flow and improve session handling.
- Removed unused ListePaneli component to clean up the codebase.
2026-08-06 02:27:42 +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 "@/components/manuel-liste/liste-cekmecesi-lazy";
import { KaydetBannerLazy } from "@/components/manuel-liste/kaydet-banner-lazy";
import { TercihProfiliKapisiLazy } from "@/components/manuel-liste/tercih-profili-kapisi-lazy";
import { HeaderGate } from "@/components/header-gate";
import { ProgressiveBlur } from "@/components/ui/skiper-ui/skiper41";
import { DevPanel } from "@/components/dev/dev-panel";
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ışmanın onda bir fiyatına, 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`}
>
{/* Rybbit analitik — beforeInteractive her zaman <head> içine defer olarak
enjekte edilir. 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 — path tek satırda toplanır. */}
{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="beforeInteractive"
/>
) : null}
<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 hiç render edilmez */}
{process.env.NODE_ENV !== "production" ? <DevPanel /> : null}
<JsonLd data={organizationJsonLd()} />
<JsonLd data={webSiteJsonLd()} />
</body>
</html>
);
}