diff --git a/components.json b/components.json
index cfcd5f1..cb51d7a 100644
--- a/components.json
+++ b/components.json
@@ -22,6 +22,7 @@
"hooks": "@/hooks"
},
"registries": {
- "@skiper-ui": "https://skiper-ui.com/registry/{name}.json"
+ "@skiper-ui": "https://skiper-ui.com/registry/{name}.json",
+ "@magicui": "https://magicui.design/r/{name}"
}
}
diff --git a/src/app/globals.css b/src/app/globals.css
index c5c418e..e87a933 100644
--- a/src/app/globals.css
+++ b/src/app/globals.css
@@ -215,4 +215,4 @@
/* scroll-behavior: smooth KULLANMA — Lenis (ScrollFlow, anchors: true)
kaydırmayı zaten yumuşatıyor; ikisi birlikte çift yumuşatma yapar. */
}
-}
+}
\ No newline at end of file
diff --git a/src/app/opengraph-image.alt.txt b/src/app/opengraph-image.alt.txt
deleted file mode 100644
index e731f02..0000000
--- a/src/app/opengraph-image.alt.txt
+++ /dev/null
@@ -1 +0,0 @@
-KolayTercih — YKS tercihin, gerçek YÖK Atlas verisiyle. Sıralamanı gir, dengeli 24 tercihlik listeni al.
diff --git a/src/app/opengraph-image.png b/src/app/opengraph-image.png
deleted file mode 100644
index d6dcce3..0000000
Binary files a/src/app/opengraph-image.png and /dev/null differ
diff --git a/src/app/opengraph-image.tsx b/src/app/opengraph-image.tsx
new file mode 100644
index 0000000..d6776c2
--- /dev/null
+++ b/src/app/opengraph-image.tsx
@@ -0,0 +1,92 @@
+import { ImageResponse } from "next/og";
+import { loadSiteOgFonts } from "@/lib/og-fonts";
+
+export const alt =
+ "KolayTercih — YKS tercihin, gerçek YÖK Atlas verisiyle. Sıralamanı gir, dengeli 24 tercihlik listeni al.";
+export const size = { width: 1200, height: 630 };
+export const contentType = "image/png";
+
+export default async function OpenGraphImage() {
+ const fonts = await loadSiteOgFonts();
+
+ return new ImageResponse(
+ (
+
+
+
+
+
+
+
+
+
+ Kolay
+ Tercih
+
+
+
+
+ YKS tercihin, gerçek YÖK Atlas verisiyle
+
+
+
+ Sıralamanı gir · Dengeli 24 tercihlik listeni al
+
+
+
+ ),
+ { ...size, fonts },
+ );
+}
diff --git a/src/app/rehber/[slug]/opengraph-image.tsx b/src/app/rehber/[slug]/opengraph-image.tsx
index cdca730..33bc1ec 100644
--- a/src/app/rehber/[slug]/opengraph-image.tsx
+++ b/src/app/rehber/[slug]/opengraph-image.tsx
@@ -1,5 +1,6 @@
import { ImageResponse } from "next/og";
import { getRehber } from "@/lib/rehber";
+import { loadRehberOgFonts } from "@/lib/og-fonts";
import {
rehberBasliginiBol,
rehberMetniniParcala,
@@ -18,6 +19,7 @@ export default async function RehberOpenGraphImage({
const yazi = getRehber(slug);
const baslik = yazi?.baslik ?? "Tercih Rehberi";
const { vurgu, kalan } = rehberBasliginiBol(baslik);
+ const fonts = await loadRehberOgFonts();
return new ImageResponse(
(
@@ -30,7 +32,7 @@ export default async function RehberOpenGraphImage({
overflow: "hidden",
background: "white",
color: "#2563eb",
- fontFamily: "sans-serif",
+ fontFamily: "Bricolage Grotesque",
}}
>
{[
@@ -108,6 +110,7 @@ export default async function RehberOpenGraphImage({
style={{
display: "flex",
alignItems: "center",
+ fontFamily: "Clarity City",
fontSize: 20,
fontWeight: 700,
letterSpacing: "0.18em",
@@ -123,8 +126,9 @@ export default async function RehberOpenGraphImage({
display: "flex",
flexWrap: "wrap",
maxWidth: 980,
+ fontFamily: "Cal Sans",
fontSize: baslik.length > 70 ? 48 : baslik.length > 52 ? 54 : 62,
- fontWeight: 300,
+ fontWeight: 400,
lineHeight: 1.02,
letterSpacing: "-0.025em",
color: "#2563eb",
@@ -133,8 +137,9 @@ export default async function RehberOpenGraphImage({
@@ -144,6 +149,7 @@ export default async function RehberOpenGraphImage({
key={i}
style={{
display: "flex",
+ fontFamily: "Bricolage Grotesque",
fontStyle: "italic",
fontWeight: 800,
}}
@@ -168,6 +174,7 @@ export default async function RehberOpenGraphImage({
key={i}
style={{
display: "flex",
+ fontFamily: "Bricolage Grotesque",
fontStyle: "italic",
fontWeight: 800,
}}
@@ -203,18 +210,19 @@ export default async function RehberOpenGraphImage({
style={{
display: "flex",
marginLeft: 2,
+ fontFamily: "Bricolage Grotesque",
fontSize: 24,
letterSpacing: "-0.05em",
color: "#2563eb",
}}
>
Kolay
- Tercih
+ Tercih
),
- size,
+ { ...size, fonts },
);
}
diff --git a/src/components/katalog-arama.tsx b/src/components/katalog-arama.tsx
index 22a17a1..bef280b 100644
--- a/src/components/katalog-arama.tsx
+++ b/src/components/katalog-arama.tsx
@@ -122,7 +122,7 @@ export function KatalogArama() {
type="button"
onClick={() => setAcik(true)}
aria-label="Bölüm veya üniversite ara"
- className="ml-auto flex size-10 cursor-pointer items-center justify-center rounded-full border border-slate-200 bg-white text-slate-700 transition-[background-color,transform] duration-150 hover:bg-slate-100 active:scale-[0.96] sm:hidden"
+ className="ml-auto flex size-9 shrink-0 cursor-pointer items-center justify-center rounded-full border border-slate-200 bg-white text-slate-700 transition-[background-color,transform] duration-150 hover:bg-slate-100 active:scale-[0.96] sm:hidden"
>
diff --git a/src/components/manuel-liste/listem-butonu.tsx b/src/components/manuel-liste/listem-butonu.tsx
index 1c7b97f..89ffa23 100644
--- a/src/components/manuel-liste/listem-butonu.tsx
+++ b/src/components/manuel-liste/listem-butonu.tsx
@@ -29,9 +29,9 @@ export function ListemButonu() {
aria-expanded={acik}
aria-label={`Seçtiklerim — ${liste.length}/${MANUEL_LISTE_MAX} program`}
title="Tablodan seçtiğin programlar"
- className="relative inline-flex h-12 cursor-pointer items-center gap-2 whitespace-nowrap rounded-full border border-slate-200 bg-white px-5 text-sm font-semibold text-slate-700 transition-[color,background-color,border-color,transform] duration-200 hover:border-slate-300 hover:bg-slate-50 active:scale-[0.97]"
+ className="relative inline-flex h-9 cursor-pointer items-center gap-1.5 whitespace-nowrap rounded-full border border-slate-200 bg-white px-3 text-xs font-semibold text-slate-700 transition-[color,background-color,border-color,transform] duration-200 hover:border-slate-300 hover:bg-slate-50 active:scale-[0.97] sm:h-12 sm:gap-2 sm:px-5 sm:text-sm"
>
-
+
Seçtiklerim
{liste.length > 0 ? (
// key=length: her eklemede rozet yeniden doğar ve spring ile oturur
diff --git a/src/components/sign-out-button.tsx b/src/components/sign-out-button.tsx
index 5f2e2e1..a23cc01 100644
--- a/src/components/sign-out-button.tsx
+++ b/src/components/sign-out-button.tsx
@@ -11,14 +11,14 @@ export function SignOutButton() {
{
await authClient.signOut();
router.refresh();
}}
>
-
+
);
}
diff --git a/src/components/site-header.tsx b/src/components/site-header.tsx
index 81791d6..e7d82df 100644
--- a/src/components/site-header.tsx
+++ b/src/components/site-header.tsx
@@ -6,11 +6,11 @@ import { UserNav, UserNavFallback } from "@/components/user-nav";
export function SiteHeader() {
return (
-
-
+
+
-
- Kolay
-
+
+
+ Kolay
+
+
Tercih
diff --git a/src/components/user-nav.tsx b/src/components/user-nav.tsx
index f5c55f6..dc33dd6 100644
--- a/src/components/user-nav.tsx
+++ b/src/components/user-nav.tsx
@@ -11,8 +11,8 @@ import { SignOutButton } from "./sign-out-button";
*/
export function UserNavFallback() {
return (
-
-
+
);
}
@@ -23,11 +23,11 @@ export async function UserNav() {
// Manuel liste localStorage'ta yaşadığı için Listem girişsiz de çalışır
if (!u) {
return (
-
+
Giriş yap
@@ -36,15 +36,16 @@ export async function UserNav() {
}
return (
-
+
-
- {u.creditBalance} kredi
+
+ {u.creditBalance}
+ kredi
diff --git a/src/fonts/og/ClarityCity-Bold.ttf b/src/fonts/og/ClarityCity-Bold.ttf
new file mode 100644
index 0000000..bb92c9f
Binary files /dev/null and b/src/fonts/og/ClarityCity-Bold.ttf differ
diff --git a/src/fonts/og/ClarityCity-Light.ttf b/src/fonts/og/ClarityCity-Light.ttf
new file mode 100644
index 0000000..f935896
Binary files /dev/null and b/src/fonts/og/ClarityCity-Light.ttf differ
diff --git a/src/fonts/og/ClarityCity-SemiBold.ttf b/src/fonts/og/ClarityCity-SemiBold.ttf
new file mode 100644
index 0000000..ca5c083
Binary files /dev/null and b/src/fonts/og/ClarityCity-SemiBold.ttf differ
diff --git a/src/fonts/og/bricolage-grotesque-latin-300-normal.woff b/src/fonts/og/bricolage-grotesque-latin-300-normal.woff
new file mode 100644
index 0000000..35200bf
Binary files /dev/null and b/src/fonts/og/bricolage-grotesque-latin-300-normal.woff differ
diff --git a/src/fonts/og/bricolage-grotesque-latin-600-normal.woff b/src/fonts/og/bricolage-grotesque-latin-600-normal.woff
new file mode 100644
index 0000000..a0b1b60
Binary files /dev/null and b/src/fonts/og/bricolage-grotesque-latin-600-normal.woff differ
diff --git a/src/fonts/og/bricolage-grotesque-latin-800-normal.woff b/src/fonts/og/bricolage-grotesque-latin-800-normal.woff
new file mode 100644
index 0000000..5ffe9d7
Binary files /dev/null and b/src/fonts/og/bricolage-grotesque-latin-800-normal.woff differ
diff --git a/src/fonts/og/bricolage-grotesque-latin-ext-300-normal.woff b/src/fonts/og/bricolage-grotesque-latin-ext-300-normal.woff
new file mode 100644
index 0000000..aa4be3a
Binary files /dev/null and b/src/fonts/og/bricolage-grotesque-latin-ext-300-normal.woff differ
diff --git a/src/fonts/og/bricolage-grotesque-latin-ext-600-normal.woff b/src/fonts/og/bricolage-grotesque-latin-ext-600-normal.woff
new file mode 100644
index 0000000..84334f4
Binary files /dev/null and b/src/fonts/og/bricolage-grotesque-latin-ext-600-normal.woff differ
diff --git a/src/fonts/og/bricolage-grotesque-latin-ext-800-normal.woff b/src/fonts/og/bricolage-grotesque-latin-ext-800-normal.woff
new file mode 100644
index 0000000..988e558
Binary files /dev/null and b/src/fonts/og/bricolage-grotesque-latin-ext-800-normal.woff differ
diff --git a/src/fonts/og/cal-sans-latin-400-normal.woff b/src/fonts/og/cal-sans-latin-400-normal.woff
new file mode 100644
index 0000000..687442d
Binary files /dev/null and b/src/fonts/og/cal-sans-latin-400-normal.woff differ
diff --git a/src/fonts/og/cal-sans-latin-ext-400-normal.woff b/src/fonts/og/cal-sans-latin-ext-400-normal.woff
new file mode 100644
index 0000000..b3ca3b1
Binary files /dev/null and b/src/fonts/og/cal-sans-latin-ext-400-normal.woff differ
diff --git a/src/lib/og-fonts.ts b/src/lib/og-fonts.ts
new file mode 100644
index 0000000..c974ef4
--- /dev/null
+++ b/src/lib/og-fonts.ts
@@ -0,0 +1,129 @@
+import { readFile } from "node:fs/promises";
+import { join } from "node:path";
+
+const OG_FONT_DIR = join(process.cwd(), "src/fonts/og");
+
+function toArrayBuffer(buf: Buffer): ArrayBuffer {
+ return buf.buffer.slice(
+ buf.byteOffset,
+ buf.byteOffset + buf.byteLength,
+ ) as ArrayBuffer;
+}
+
+async function loadFont(fileName: string): Promise
{
+ return toArrayBuffer(await readFile(join(OG_FONT_DIR, fileName)));
+}
+
+type OgFont = {
+ name: string;
+ data: ArrayBuffer;
+ weight: 300 | 400 | 600 | 700 | 800;
+ style: "normal" | "italic";
+};
+
+/** latin + latin-ext çiftini aynı aile/ağırlıkta kaydeder (Türkçe glifler için). */
+async function latinPair(
+ name: string,
+ weight: OgFont["weight"],
+ latinFile: string,
+ latinExtFile: string,
+ style: OgFont["style"] = "normal",
+): Promise {
+ const [latin, latinExt] = await Promise.all([
+ loadFont(latinFile),
+ loadFont(latinExtFile),
+ ]);
+ return [
+ { name, data: latin, weight, style },
+ { name, data: latinExt, weight, style },
+ ];
+}
+
+/** Ana sayfa OG: Bricolage (marka) + ClarityCity (gövde). */
+export async function loadSiteOgFonts(): Promise {
+ const [bricolage, clarityLight, claritySemiBold] = await Promise.all([
+ Promise.all([
+ latinPair(
+ "Bricolage Grotesque",
+ 300,
+ "bricolage-grotesque-latin-300-normal.woff",
+ "bricolage-grotesque-latin-ext-300-normal.woff",
+ ),
+ latinPair(
+ "Bricolage Grotesque",
+ 600,
+ "bricolage-grotesque-latin-600-normal.woff",
+ "bricolage-grotesque-latin-ext-600-normal.woff",
+ ),
+ ]).then((pairs) => pairs.flat()),
+ loadFont("ClarityCity-Light.ttf"),
+ loadFont("ClarityCity-SemiBold.ttf"),
+ ]);
+
+ return [
+ ...bricolage,
+ {
+ name: "Clarity City",
+ data: clarityLight,
+ weight: 300,
+ style: "normal",
+ },
+ {
+ name: "Clarity City",
+ data: claritySemiBold,
+ weight: 600,
+ style: "normal",
+ },
+ ];
+}
+
+/** Rehber kapak OG: ClarityCity + Cal Sans + Bricolage. */
+export async function loadRehberOgFonts(): Promise {
+ const [clarityBold, calSans, light, semiBold, extraBold] = await Promise.all([
+ loadFont("ClarityCity-Bold.ttf"),
+ latinPair(
+ "Cal Sans",
+ 400,
+ "cal-sans-latin-400-normal.woff",
+ "cal-sans-latin-ext-400-normal.woff",
+ ),
+ latinPair(
+ "Bricolage Grotesque",
+ 300,
+ "bricolage-grotesque-latin-300-normal.woff",
+ "bricolage-grotesque-latin-ext-300-normal.woff",
+ ),
+ latinPair(
+ "Bricolage Grotesque",
+ 600,
+ "bricolage-grotesque-latin-600-normal.woff",
+ "bricolage-grotesque-latin-ext-600-normal.woff",
+ ),
+ latinPair(
+ "Bricolage Grotesque",
+ 800,
+ "bricolage-grotesque-latin-800-normal.woff",
+ "bricolage-grotesque-latin-ext-800-normal.woff",
+ ),
+ ]);
+
+ // Sitede italic kullanılıyor; ayrı italic dosya yok — aynı kesimi italic olarak kaydet.
+ const extraBoldItalic = extraBold.map((font) => ({
+ ...font,
+ style: "italic" as const,
+ }));
+
+ return [
+ {
+ name: "Clarity City",
+ data: clarityBold,
+ weight: 700,
+ style: "normal",
+ },
+ ...calSans,
+ ...light,
+ ...semiBold,
+ ...extraBold,
+ ...extraBoldItalic,
+ ];
+}