Skip to content

Commit 73d3bfa

Browse files
committed
[WIP] Setup og image endpoints: one for generating image itself (/api/og-image.svg) and the other for testing purposes (/api/get-og-image-url).
1 parent 163c066 commit 73d3bfa

File tree

4 files changed

+119
-1
lines changed

4 files changed

+119
-1
lines changed

astro.config.mjs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,19 @@ import starlightOpenAPI, { openAPISidebarGroups } from "starlight-openapi";
77
import vercel from "@astrojs/vercel";
88
import remarkMath from "remark-math";
99
import rehypeKatex from "rehype-katex";
10+
import { getEnvsSchema } from "./src/lib/og-image/schema.mjs";
11+
12+
const isProduction = process.env.NODE_ENV === "production";
1013

1114
// https://astro.build/config
1215
export default defineConfig({
13-
site: "https://aptos.dev",
16+
site: isProduction ? "https://aptos.dev" : "http://localhost:4321",
17+
env: {
18+
schema: {
19+
...getEnvsSchema(),
20+
},
21+
validateSecrets: true,
22+
},
1423
integrations: [
1524
starlight({
1625
title: "Aptos Developer Docs",

public/fonts/DMMono-Light.ttf

47.7 KB
Binary file not shown.

src/pages/api/get-og-image-url.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import type { APIRoute } from "astro";
2+
import { optionsSchema } from "./og-image.svg";
3+
import { getImageUrl } from "~/lib/og-image/getImageUrl";
4+
5+
export const prerender = false;
6+
export const GET: APIRoute = ({ request }) => {
7+
const url = new URL(request.url);
8+
const options = optionsSchema.parse({
9+
title: url.searchParams.get("title"),
10+
description: url.searchParams.get("description"),
11+
});
12+
13+
return new Response(getImageUrl(new URL("/api/og-image.svg", request.url), options));
14+
};

src/pages/api/og-image.svg.ts

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import fs from "node:fs/promises";
2+
import path from "node:path";
3+
import type { APIRoute } from "astro";
4+
import { z } from "astro:schema";
5+
import { generateImage } from "~/lib/og-image/generateImage";
6+
import { parseTokenOptions } from "~/lib/og-image/parseTokenOptions";
7+
8+
export const optionsSchema = z.object({
9+
title: z.string(),
10+
description: z.string(),
11+
});
12+
const fontDefinitions = [
13+
{
14+
name: "DMMono Light",
15+
data: fs.readFile(path.resolve("public/fonts/DMMono-Light.ttf")),
16+
weight: 400,
17+
style: "normal",
18+
},
19+
] as const;
20+
21+
export const prerender = false;
22+
export const GET: APIRoute = async ({ request }) => {
23+
const url = new URL(request.url);
24+
const { title, description } = parseTokenOptions(url.searchParams.get("token"), optionsSchema);
25+
26+
const fonts = await Promise.all(
27+
fontDefinitions.map(async (fontDefinition) => ({
28+
...fontDefinition,
29+
data: await fontDefinition.data,
30+
})),
31+
);
32+
const image = await generateImage({ width: 1200, height: 630, fonts, embedFont: true })`
33+
<div
34+
style="
35+
font-family: DMMono Light;
36+
background: #fefbfb;
37+
width: 100%;
38+
height: 100%;
39+
display: flex;
40+
align-items: center;
41+
justify-content: center;
42+
"
43+
>
44+
<div
45+
style="
46+
border: 4px solid #000;
47+
background: #fefbfb;
48+
border-radius: 4px;
49+
display: flex;
50+
justify-content: center;
51+
margin: 2rem;
52+
width: 88%;
53+
height: 80%;
54+
"
55+
>
56+
<div
57+
style="
58+
display: flex;
59+
flex-direction: column;
60+
margin: 20px;
61+
width: 90%;
62+
height: 90%;
63+
"
64+
>
65+
<p
66+
style="
67+
font-size: 72px;
68+
font-weight: bold;
69+
max-height: 84%;
70+
overflow: hidden;
71+
"
72+
>
73+
${title}
74+
</p>
75+
<div
76+
style="
77+
width: 100%;
78+
margin-bottom: 8px;
79+
font-size: 28px;
80+
"
81+
>
82+
${description}
83+
</div>
84+
</div>
85+
</div>
86+
</div>
87+
`;
88+
89+
return new Response(image, {
90+
headers: {
91+
"Content-Type": "image/svg+xml",
92+
"Cache-Control": "public, max-age=3600", // Optional: Cache control
93+
},
94+
});
95+
};

0 commit comments

Comments
 (0)