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() { ); } 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 ( -
+
@@ -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, + ]; +}