238 lines
6.2 KiB
TypeScript
238 lines
6.2 KiB
TypeScript
import { ImageResponse } from "next/og";
|
||
import { loadRehberOgFonts } from "@/lib/og-fonts";
|
||
|
||
export const OG_SIZE = { width: 1200, height: 630 };
|
||
export const OG_CONTENT_TYPE = "image/png";
|
||
|
||
const PIXELS: [number, number, number][] = [
|
||
[960, 50, 0.16],
|
||
[980, 50, 0.28],
|
||
[1020, 50, 0.12],
|
||
[940, 70, 0.24],
|
||
[980, 70, 0.12],
|
||
[1000, 70, 0.3],
|
||
[1060, 70, 0.18],
|
||
[960, 90, 0.12],
|
||
[1000, 90, 0.2],
|
||
[1040, 90, 0.1],
|
||
[1080, 90, 0.26],
|
||
[1080, 110, 0.14],
|
||
[1120, 110, 0.22],
|
||
[1140, 110, 0.12],
|
||
[60, 490, 0.12],
|
||
[100, 490, 0.25],
|
||
[120, 490, 0.14],
|
||
[40, 510, 0.24],
|
||
[80, 510, 0.12],
|
||
[120, 510, 0.3],
|
||
[160, 510, 0.16],
|
||
[60, 530, 0.14],
|
||
[100, 530, 0.22],
|
||
[140, 530, 0.1],
|
||
[180, 530, 0.27],
|
||
];
|
||
|
||
function baslikBoyutu(title: string): number {
|
||
if (title.length > 70) return 44;
|
||
if (title.length > 52) return 50;
|
||
if (title.length > 36) return 56;
|
||
return 62;
|
||
}
|
||
|
||
/** Sayfa OG kartı — rehber kapağıyla aynı dil: eyebrow, başlık, marka. */
|
||
export async function createOgSayfaImage(opts: {
|
||
eyebrow: string;
|
||
title: string;
|
||
description?: string;
|
||
/** data: URI — sağ üstte beyaz rozet içinde gösterilir (üniversite logosu). */
|
||
logo?: string;
|
||
}): Promise<ImageResponse> {
|
||
const fonts = await loadRehberOgFonts();
|
||
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: "Bricolage Grotesque",
|
||
}}
|
||
>
|
||
{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%",
|
||
padding: "58px 68px 52px",
|
||
}}
|
||
>
|
||
<div
|
||
style={{
|
||
display: "flex",
|
||
alignItems: "center",
|
||
fontFamily: "Clarity City",
|
||
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={{
|
||
display: "flex",
|
||
flexDirection: "column",
|
||
maxWidth: 980,
|
||
gap: 18,
|
||
}}
|
||
>
|
||
<div
|
||
style={{
|
||
display: "flex",
|
||
flexWrap: "wrap",
|
||
fontFamily: "Cal Sans",
|
||
fontSize: baslikBoyutu(title),
|
||
fontWeight: 400,
|
||
lineHeight: 1.05,
|
||
letterSpacing: "-0.025em",
|
||
color: "#2563eb",
|
||
}}
|
||
>
|
||
{title}
|
||
</div>
|
||
{description ? (
|
||
<div
|
||
style={{
|
||
display: "flex",
|
||
fontFamily: "Clarity City",
|
||
fontSize: 26,
|
||
fontWeight: 700,
|
||
lineHeight: 1.35,
|
||
color: "#64748b",
|
||
maxWidth: 860,
|
||
}}
|
||
>
|
||
{description}
|
||
</div>
|
||
) : null}
|
||
</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",
|
||
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>
|
||
</div>
|
||
</div>
|
||
),
|
||
{ ...OG_SIZE, fonts },
|
||
);
|
||
}
|