fix(og): rehber kapak başlığı taşmıyor, İ/ş/ğ doğru yazı tipinden geliyor

İki kök neden: rakamlı başlıklarda karışık flex span satır kaydıramıyordu
(başlık artık kelime kelime kutulanıyor); Satori aynı aile adıyla kaydedilen
latin/latin-ext dosyalarından yalnızca birini kullanıyordu (ext alt-kümeleri
'<ad> Ext' adıyla kayıtlı, şablonlar OG_AILE virgüllü aile listesini veriyor).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
bilalgursen
2026-09-24 17:42:29 +03:00
parent 9d90436027
commit 6094066c5e
4 changed files with 400 additions and 370 deletions

View File

@@ -21,7 +21,24 @@ type OgFont = {
style: "normal" | "italic";
};
/** latin + latin-ext çiftini aynı aile/ağırlıkta kaydeder (Türkçe glifler için). */
/**
* Satori aynı aile adı + ağırlık için TEK dosya seçer (`get()` en iyi eşleşen
* tek kaydı döndürür); iki alt-kümeyi aynı adla kaydetmek latin-ext dosyasını
* fiilen devre dışı bırakıyordu — İ/ş/ğ gibi glifler başka bir aileden
* (kayıt sırasına göre Clarity City) geliyor, ölçüm ile çizim ayrışıyor ve
* "İ" ile başlayan kelimeden sonraki boşluk yutuluyordu. Bu yüzden ext
* alt-kümesi `<ad> Ext` adıyla ayrı kaydedilir; şablonlar `fontFamily`'ye
* aşağıdaki OG_AILE değerlerini verir (Satori CSS gibi virgüllü METİN ister,
* dizi verilirse `split` hatasıyla çöker); glif ilk dosyada yoksa ikinciye
* geçer.
*/
export const OG_AILE = {
calSans: "Cal Sans, Cal Sans Ext",
bricolage: "Bricolage Grotesque, Bricolage Grotesque Ext",
clarity: "Clarity City",
} as const;
/** latin + latin-ext çiftini kaydeder; ext alt-kümesi `<ad> Ext` adını alır. */
async function latinPair(
name: string,
weight: OgFont["weight"],
@@ -35,7 +52,7 @@ async function latinPair(
]);
return [
{ name, data: latin, weight, style },
{ name, data: latinExt, weight, style },
{ name: `${name} Ext`, data: latinExt, weight, style },
];
}

View File

@@ -1,5 +1,5 @@
import { ImageResponse } from "next/og";
import { loadRehberOgFonts } from "@/lib/og-fonts";
import { loadRehberOgFonts, OG_AILE } from "@/lib/og-fonts";
export const OG_SIZE = { width: 1200, height: 630 };
export const OG_CONTENT_TYPE = "image/png";
@@ -51,187 +51,185 @@ export async function createOgSayfaImage(opts: {
const { eyebrow, title, description, logo } = opts;
return new ImageResponse(
(
<div
style={{
position: "relative",
display: "flex",
width: "100%",
height: "100%",
overflow: "hidden",
background: "white",
color: "#2563eb",
fontFamily: OG_AILE.bricolage,
}}
>
{PIXELS.map(([left, top, opacity], i) => (
<span
key={i}
style={{
position: "absolute",
display: "flex",
left,
top,
width: 14,
height: 14,
borderRadius: 4,
background: "#2563eb",
opacity,
}}
/>
))}
<span
style={{
position: "absolute",
display: "flex",
left: 1040,
top: 50,
width: 14,
height: 14,
borderRadius: 4,
background: "#ff5a00",
opacity: 0.8,
}}
/>
<span
style={{
position: "absolute",
display: "flex",
left: 80,
top: 530,
width: 14,
height: 14,
borderRadius: 4,
background: "#ff5a00",
opacity: 0.8,
}}
/>
<div
style={{
position: "absolute",
width: "100%",
height: "100%",
border: "2px solid rgba(37,99,235,0.15)",
}}
/>
<div
style={{
position: "relative",
display: "flex",
flexDirection: "column",
justifyContent: "space-between",
width: "100%",
height: "100%",
overflow: "hidden",
background: "white",
color: "#2563eb",
fontFamily: "Bricolage Grotesque",
padding: "58px 68px 52px",
}}
>
{PIXELS.map(([left, top, opacity], i) => (
<span
key={i}
style={{
position: "absolute",
display: "flex",
left,
top,
width: 14,
height: 14,
borderRadius: 4,
background: "#2563eb",
opacity,
}}
/>
))}
<span
style={{
position: "absolute",
display: "flex",
left: 1040,
top: 50,
width: 14,
height: 14,
borderRadius: 4,
background: "#ff5a00",
opacity: 0.8,
}}
/>
<span
style={{
position: "absolute",
display: "flex",
left: 80,
top: 530,
width: 14,
height: 14,
borderRadius: 4,
background: "#ff5a00",
opacity: 0.8,
}}
/>
<div
style={{
position: "absolute",
width: "100%",
height: "100%",
border: "2px solid rgba(37,99,235,0.15)",
display: "flex",
alignItems: "center",
fontFamily: OG_AILE.clarity,
fontSize: 20,
fontWeight: 700,
letterSpacing: "0.18em",
textTransform: "uppercase",
color: "#2563eb",
}}
/>
>
<span>{eyebrow}</span>
{logo ? (
<span
style={{
display: "flex",
marginLeft: "auto",
alignItems: "center",
justifyContent: "center",
width: 108,
height: 108,
borderRadius: 24,
background: "white",
border: "2px solid rgba(37,99,235,0.15)",
boxShadow: "0 8px 24px rgba(15,23,42,0.08)",
}}
>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img src={logo} alt="" width={84} height={84} />
</span>
) : null}
</div>
<div
style={{
position: "relative",
display: "flex",
flexDirection: "column",
justifyContent: "space-between",
width: "100%",
padding: "58px 68px 52px",
maxWidth: 980,
gap: 18,
}}
>
<div
style={{
display: "flex",
alignItems: "center",
fontFamily: "Clarity City",
fontSize: 20,
fontWeight: 700,
letterSpacing: "0.18em",
textTransform: "uppercase",
flexWrap: "wrap",
fontFamily: OG_AILE.calSans,
fontSize: baslikBoyutu(title),
fontWeight: 400,
lineHeight: 1.05,
letterSpacing: "-0.025em",
color: "#2563eb",
}}
>
<span>{eyebrow}</span>
{logo ? (
<span
style={{
display: "flex",
marginLeft: "auto",
alignItems: "center",
justifyContent: "center",
width: 108,
height: 108,
borderRadius: 24,
background: "white",
border: "2px solid rgba(37,99,235,0.15)",
boxShadow: "0 8px 24px rgba(15,23,42,0.08)",
}}
>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img src={logo} alt="" width={84} height={84} />
</span>
) : null}
{title}
</div>
<div
style={{
display: "flex",
flexDirection: "column",
maxWidth: 980,
gap: 18,
}}
>
{description ? (
<div
style={{
display: "flex",
flexWrap: "wrap",
fontFamily: "Cal Sans",
fontSize: baslikBoyutu(title),
fontWeight: 400,
lineHeight: 1.05,
letterSpacing: "-0.025em",
color: "#2563eb",
fontFamily: OG_AILE.clarity,
fontSize: 26,
fontWeight: 700,
lineHeight: 1.35,
color: "#64748b",
maxWidth: 860,
}}
>
{title}
{description}
</div>
{description ? (
<div
style={{
display: "flex",
fontFamily: "Clarity City",
fontSize: 26,
fontWeight: 700,
lineHeight: 1.35,
color: "#64748b",
maxWidth: 860,
}}
>
{description}
</div>
) : null}
</div>
) : null}
</div>
<div
<div
style={{
display: "flex",
alignItems: "center",
justifyContent: "flex-end",
}}
>
<svg
width="38"
height="38"
viewBox="0 0 180 180"
style={{ display: "flex" }}
>
<rect x="27" y="56" width="57" height="57" rx="13" fill="#3b82f6" />
<rect x="91" y="29" width="56" height="56" rx="13" fill="#fdc7a7" />
<rect x="91" y="95" width="56" height="56" rx="13" fill="#ff5a00" />
</svg>
<span
style={{
display: "flex",
alignItems: "center",
justifyContent: "flex-end",
marginLeft: 2,
fontFamily: OG_AILE.bricolage,
fontSize: 24,
letterSpacing: "-0.05em",
color: "#2563eb",
}}
>
<svg
width="38"
height="38"
viewBox="0 0 180 180"
style={{ display: "flex" }}
>
<rect x="27" y="56" width="57" height="57" rx="13" fill="#3b82f6" />
<rect x="91" y="29" width="56" height="56" rx="13" fill="#fdc7a7" />
<rect x="91" y="95" width="56" height="56" rx="13" fill="#ff5a00" />
</svg>
<span
style={{
display: "flex",
marginLeft: 2,
fontFamily: "Bricolage Grotesque",
fontSize: 24,
letterSpacing: "-0.05em",
color: "#2563eb",
}}
>
<span style={{ fontWeight: 300 }}>Kolay</span>
<span style={{ fontWeight: 600 }}>Tercih</span>
</span>
</div>
<span style={{ fontWeight: 300 }}>Kolay</span>
<span style={{ fontWeight: 600 }}>Tercih</span>
</span>
</div>
</div>
),
</div>,
{ ...OG_SIZE, fonts },
);
}