wrath/src/pages/[lang]/posts/[slug]/og.png.ts
2025-11-19 00:24:33 +01:00

114 lines
3 KiB
TypeScript

import { getCollection, type CollectionEntry } from "astro:content"
import fs from "fs"
import { join, resolve } from "node:path"
import { ImageResponse } from "@vercel/og"
import { getPostsByLocale } from "~/utils"
import type { ReactElement } from "react"
interface Props {
params: { slug: string }
props: { post: CollectionEntry<"enPosts" | "dePosts"> }
}
export async function getStaticPaths() {
const blogPostsEN = await getPostsByLocale("en")
const blogPostsDE = await getPostsByLocale("de")
const posts = [...blogPostsEN, ...blogPostsDE]
return posts.map((post) => ({
params: { slug: post.id, lang: post.data.lang },
props: { post },
}))
}
export async function GET({ props }: Props) {
const options = {
width: 1200,
height: 600,
padding: 10,
color: "#FFB900",
}
const { post } = props
const path = join(process.cwd(), "public", "fonts", "JetBrainsMono-Bold.ttf")
// using custom font files
const jetbrainsMono = fs.readFileSync(path)
// Astro doesn't support tsx endpoints so usign React-element objects
const html = {
type: "div",
key: "extra-margin",
props: {
style: {
display: "flex",
width: options.width,
height: options.height,
backgroundColor: options.color,
padding: options.padding,
boxSizing: "border-box",
},
children: [
{
type: "div",
props: {
style: {
display: "flex",
width: "100%",
height: "100%",
backgroundColor: options.color,
position: "relative",
overflow: "hidden",
},
children: [
{
type: "img",
props: {
src: "https://pogge.rs/i/36b0b9ec4980.png",
alt: "logo",
style: {
position: "absolute",
top: 32,
right: 32,
width: 465.18,
height: 141,
},
},
},
{
type: "div",
props: {
style: {
position: "absolute",
left: 48,
bottom: 48,
width: 1000,
color: "#222",
fontFamily: "monospace",
fontWeight: "bold",
fontSize: 58,
lineHeight: 1.2,
whiteSpace: "pre-wrap",
textAlign: "left",
display: "block",
},
children: post.data.title,
},
},
],
},
},
],
},
} as unknown as ReactElement
return new ImageResponse(html, {
width: options.width,
height: options.height,
fonts: [
{
name: "monospace",
// @ts-ignore
data: jetbrainsMono.buffer,
style: "normal",
},
],
})
}