aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/pages/og
diff options
context:
space:
mode:
Diffstat (limited to 'src/pages/og')
-rw-r--r--src/pages/og/[slug].png.ts114
1 files changed, 114 insertions, 0 deletions
diff --git a/src/pages/og/[slug].png.ts b/src/pages/og/[slug].png.ts
new file mode 100644
index 0000000..52b790b
--- /dev/null
+++ b/src/pages/og/[slug].png.ts
@@ -0,0 +1,114 @@
+import satori from "satori";
+import { Resvg } from "@resvg/resvg-js";
+import { readFileSync } from "node:fs";
+
+const pages: Record<string, string> = {
+ index: "だれもがしあわせに暮らせるまちへ",
+ jisseki: "実績",
+ policy: "私の方針",
+ support: "ご支援",
+ contact: "コンタクト",
+ "whisper-to-ai-moji-okoshi":
+ "無料・超高精度のWhisper + 生成AIで文字起こしする方法",
+ "koubunsyo-kanri": "公文書管理の不正追及の軌跡",
+ "ijime-judai-jitai": "いじめ重大事態への対応の軌跡",
+ "fukushi-shisetsu-gyakutai": "障害者福祉施設における虐待通報対応の軌跡",
+ "aiki-kouen": "合気公園の軌跡",
+ "joutyo-koteikyu": "情緒固定級の軌跡",
+ "kajo-seigen-kanwa": "過剰な制限緩和の軌跡",
+ "saresio-kaihatu": "東京サレジオ学園北側開発問題の軌跡",
+ "vaccine-kyuusai-tekiseika": "ワクチン副反応救済制度の適正化の軌跡",
+ "dislexia-taiou": "ディスレクシア(読み書き障害)対応の軌跡",
+ "ippan-situmon": "一般質問",
+};
+
+export async function getStaticPaths() {
+ return Object.keys(pages).map((slug) => ({ params: { slug } }));
+}
+
+const fontBuffer = readFileSync("node_modules/.noto-sans-jp.otf");
+const faceiconBuffer = readFileSync("public/img/faceicon.jpg");
+const faceiconBase64 = `data:image/jpeg;base64,${faceiconBuffer.toString("base64")}`;
+
+export async function GET({ params }: { params: { slug: string } }) {
+ const slug = params.slug;
+ const title = pages[slug] ?? "小平市議 安竹洋平 公式サイト";
+
+ const svg = await satori(
+ {
+ type: "div",
+ props: {
+ style: {
+ display: "flex",
+ width: "1200px",
+ height: "630px",
+ background: "linear-gradient(135deg, #3730a3 0%, #4f46e5 100%)",
+ color: "#ffffff",
+ fontFamily: "sans-serif",
+ padding: "60px 80px",
+ alignItems: "center",
+ gap: "48px",
+ },
+ children: [
+ {
+ type: "img",
+ props: {
+ src: faceiconBase64,
+ width: 200,
+ height: 200,
+ style: {
+ borderRadius: "50%",
+ border: "4px solid rgba(255,255,255,0.3)",
+ flexShrink: "0",
+ },
+ },
+ },
+ {
+ type: "div",
+ props: {
+ style: { display: "flex", flexDirection: "column", gap: "16px", flex: "1" },
+ children: [
+ {
+ type: "div",
+ props: {
+ style: { fontSize: "48px", fontWeight: "700", lineHeight: "1.3", letterSpacing: "-0.02em" },
+ children: title,
+ },
+ },
+ {
+ type: "div",
+ props: {
+ style: { fontSize: "28px", fontWeight: "500", opacity: "0.8", color: "#e0e7ff" },
+ children: "小平市議 安竹洋平",
+ },
+ },
+ {
+ type: "div",
+ props: {
+ style: { fontSize: "20px", fontWeight: "400", opacity: "0.5", color: "#e0e7ff", marginTop: "8px" },
+ children: "yasutakeyohei.com",
+ },
+ },
+ ],
+ },
+ },
+ ],
+ },
+ } as any,
+ {
+ width: 1200,
+ height: 630,
+ fonts: [{ name: "sans-serif", data: fontBuffer, weight: 400, style: "normal" }],
+ }
+ );
+
+ const resvg = new Resvg(svg, { fitTo: { mode: "width", value: 1200 } });
+ const pngBuffer = resvg.render().asPng();
+
+ return new Response(pngBuffer, {
+ headers: {
+ "Content-Type": "image/png",
+ "Cache-Control": "public, max-age=31536000, immutable",
+ },
+ });
+}