x
CI / Verify (push) Successful in 57s
CI / Build immutable images and deploy (push) Successful in 1m39s

This commit is contained in:
2026-08-31 01:45:45 +07:00 Unverified
parent 4bf9d9098f
commit 206d305cb0
6 changed files with 217 additions and 0 deletions
+83
View File
@@ -0,0 +1,83 @@
/* eslint-disable @next/next/no-img-element */
import { readFile } from "node:fs/promises";
import { join } from "node:path";
import { ImageResponse } from "next/og";
export const ogImageSize = { width: 1222, height: 560 } as const;
export const ogImageContentType = "image/png";
let bannerDataPromise: Promise<string> | undefined;
let fontDataPromise: Promise<Buffer> | undefined;
function shorten(value: string, length: number): string {
const normalized = value.replace(/\s+/gu, " ").trim();
return normalized.length > length
? `${normalized.slice(0, length - 1).trimEnd()}…`
: normalized;
}
function getBannerData(): Promise<string> {
bannerDataPromise ??= readFile(
join(process.cwd(), "public/web_banner.png"),
"base64",
).then((data) => `data:image/png;base64,${data}`);
return bannerDataPromise;
}
function getFontData(): Promise<Buffer> {
fontDataPromise ??= readFile(join(process.cwd(), "public/Kanit-SemiBold.ttf"));
return fontDataPromise;
}
export async function generateOgImage({
title,
sub,
}: {
title: string;
sub: string;
}) {
const [bannerSrc, kanit] = await Promise.all([getBannerData(), getFontData()]);
return new ImageResponse(
<div
style={{
display: "flex",
width: "1222px",
height: "560px",
fontFamily: "Kanit",
color: "#fff",
}}
>
<img src={bannerSrc} alt="Banner" width={1222} height={560} />
<div
style={{
fontSize: 64,
position: "absolute",
top: "160px",
left: "60px",
display: "flex",
flexDirection: "column",
right: "450px",
bottom: "100px",
}}
>
<div>{shorten(title, 24)}</div>
<div
style={{
fontSize: 24,
marginTop: "-20px",
color: "#aaa",
}}
>
{shorten(sub, 92)}
</div>
</div>
</div>,
{
...ogImageSize,
fonts: [{ name: "Kanit", data: kanit, style: "normal", weight: 600 }],
},
);
}