seo: add per-project OG image generator via next/og (pre-renders all 7 project cards at build time)

This commit is contained in:
Zac Gaetano 2026-05-01 11:15:29 -04:00
parent 9d88b52429
commit 2e92e45ee6

View file

@ -0,0 +1,123 @@
import { ImageResponse } from "next/og";
import { projects } from "@/data/projects";
export const size = { width: 1200, height: 630 };
export const contentType = "image/png";
export function generateStaticParams() {
return projects.map((p) => ({ slug: p.slug }));
}
export default async function Image({
params,
}: {
params: Promise<{ slug: string }>;
}) {
const { slug } = await params;
const project = projects.find((p) => p.slug === slug);
if (!project) {
return new ImageResponse(
<div style={{ background: "#0a0a0a", width: "100%", height: "100%" }} />,
{ ...size }
);
}
return new ImageResponse(
(
<div
style={{
background: "#0a0a0a",
width: "100%",
height: "100%",
display: "flex",
flexDirection: "column",
alignItems: "flex-start",
justifyContent: "center",
padding: "80px 80px",
position: "relative",
}}
>
{/* Brand mark top-left */}
<div
style={{
position: "absolute",
top: 56,
left: 80,
fontSize: 12,
color: "#404040",
letterSpacing: "0.25em",
}}
>
WILD DRAGON
</div>
{/* URL bottom-right */}
<div
style={{
position: "absolute",
bottom: 56,
right: 80,
fontSize: 16,
color: "#404040",
letterSpacing: "0.08em",
}}
>
wilddragon.net
</div>
{/* Accent bar */}
<div
style={{
width: 48,
height: 3,
background: "#3b82f6",
marginBottom: 36,
}}
/>
{/* Client name */}
<div
style={{
fontSize: 68,
fontWeight: 700,
color: "#ffffff",
lineHeight: 1.05,
marginBottom: 28,
maxWidth: 900,
letterSpacing: "-0.5px",
}}
>
{project.client}
</div>
{/* Category + Year row */}
<div style={{ display: "flex", alignItems: "center", gap: 20 }}>
<div
style={{
padding: "10px 20px",
background: "rgba(59,130,246,0.12)",
color: "#3b82f6",
borderRadius: 8,
fontSize: 16,
fontWeight: 500,
border: "1px solid rgba(59,130,246,0.2)",
}}
>
{project.category}
</div>
<div
style={{
fontSize: 16,
color: "#525252",
letterSpacing: "0.05em",
}}
>
{project.year}
</div>
</div>
</div>
),
{ ...size }
);
}