import { ImageResponse } from "next/og"; import { readFile } from "fs/promises"; import path from "path"; import { prisma } from "@/lib/prisma"; import { wrappedCard } from "@/lib/wrapped-card"; import type { Archetype, Period } from "@/app/(student)/wrapped/_client/types"; export const size = { width: 1080, height: 1920 }; export const contentType = "image/png"; export const dynamic = "force-dynamic"; // Серверный PNG 1080×1920 карточки Wrapped по shareToken (для OG-превью в соцсетях // и для скачивания участником). Рендерится через next/og (Satori + resvg-wasm). export default async function OG({ params }: { params: Promise<{ token: string }> }) { const { token } = await params; const run = await prisma.wrappedRun.findUnique({ where: { shareToken: token } }); const [reg, med] = await Promise.all([ readFile(path.join(process.cwd(), "public/fonts/FiraMono-Regular.ttf")), readFile(path.join(process.cwd(), "public/fonts/FiraMono-Medium.ttf")), ]); const data = run ? { noteCount: run.noteCount, linkCount: run.linkCount, tagCount: run.tagCount, topTag: run.topTag, archetype: run.archetype as Archetype | null, score: run.score, period: run.period as Period, } : { noteCount: 0, linkCount: 0, tagCount: 0, topTag: null, archetype: null, score: 0, period: "year" as Period }; return new ImageResponse(wrappedCard(data), { ...size, fonts: [ { name: "Fira Mono", data: reg, weight: 400, style: "normal" as const }, { name: "Fira Mono", data: med, weight: 500, style: "normal" as const }, ], }); }