Skip to content

Commit d3af379

Browse files
DevRediousclaude
andcommitted
feat(seo): branded Open Graph image for the home page
The home/root had no og:image (bare social previews). Add a Next file-based opengraph-image.tsx (and twitter-image.tsx reusing it): a branded card with the Resonance logo + name in Stack Sans Notch and the tagline. Switch the root twitter card to summary_large_image. Conference pages keep their own /api/og/<slug> image. Fonts traced for the new image routes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 0a99aff commit d3af379

4 files changed

Lines changed: 80 additions & 1 deletion

File tree

next.config.mjs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ const nextConfig = {
1212
// font files into the standalone output (otherwise the OG card crashes in prod).
1313
outputFileTracingIncludes: {
1414
"/api/og/[slug]": ["./src/app/fonts/*.ttf"],
15+
"/opengraph-image": ["./src/app/fonts/*.ttf"],
16+
"/twitter-image": ["./src/app/fonts/*.ttf"],
1517
},
1618
};
1719

src/app/layout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export const metadata: Metadata = {
2626
apple: "/apple-touch-icon.png",
2727
},
2828
openGraph: { title, description, url: SITE_URL, siteName: SITE_NAME, type: "website" },
29-
twitter: { card: "summary", title, description },
29+
twitter: { card: "summary_large_image", title, description },
3030
};
3131

3232
export const viewport: Viewport = {

src/app/opengraph-image.tsx

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import { readFileSync } from "node:fs";
2+
import { join } from "node:path";
3+
import { BRAND_COLOR } from "@/lib/site";
4+
import { ImageResponse } from "next/og";
5+
6+
export const runtime = "nodejs";
7+
export const alt = "Resonance — Intuition conference hub";
8+
export const size = { width: 1200, height: 630 };
9+
export const contentType = "image/png";
10+
11+
const BG = "#13100c";
12+
const CARAMEL = BRAND_COLOR;
13+
const notch = (file: string) => readFileSync(join(process.cwd(), "src/app/fonts", file));
14+
15+
function fileDataUri(publicPath: string, mime: string): string | null {
16+
try {
17+
const buf = readFileSync(join(process.cwd(), "public", publicPath.replace(/^\//, "")));
18+
return `data:${mime};base64,${buf.toString("base64")}`;
19+
} catch {
20+
return null;
21+
}
22+
}
23+
24+
// Branded Open Graph card for the home page (and any route without its own image).
25+
export default function Image() {
26+
const logo = fileDataUri("/brand/resonance/logo.svg", "image/svg+xml");
27+
28+
return new ImageResponse(
29+
<div
30+
style={{
31+
display: "flex",
32+
flexDirection: "column",
33+
justifyContent: "center",
34+
width: "100%",
35+
height: "100%",
36+
backgroundColor: BG,
37+
backgroundImage:
38+
"radial-gradient(1200px 500px at 100% 0%, rgba(224,168,106,0.18), transparent 60%)",
39+
padding: "70px 80px",
40+
fontFamily: "Stack Sans Notch",
41+
}}
42+
>
43+
<div style={{ display: "flex", alignItems: "center", gap: 28 }}>
44+
{logo ? (
45+
// biome-ignore lint/a11y/useAltText: OG image (no accessible DOM)
46+
<img src={logo} width={120} height={120} />
47+
) : null}
48+
<div style={{ display: "flex", fontSize: 110, fontWeight: 700, color: CARAMEL }}>
49+
Resonance
50+
</div>
51+
</div>
52+
<div style={{ display: "flex", fontSize: 46, color: "#fff", marginTop: 36 }}>
53+
The Intuition ecosystem, distilled.
54+
</div>
55+
<div
56+
style={{
57+
display: "flex",
58+
fontSize: 30,
59+
color: "rgba(255,255,255,0.6)",
60+
marginTop: 14,
61+
}}
62+
>
63+
Recaps of Spaces, talks & AMAs context, speakers, themes & missions.
64+
</div>
65+
</div>,
66+
{
67+
...size,
68+
fonts: [
69+
{ name: "Stack Sans Notch", data: notch("StackSansNotch-SemiBold.ttf"), weight: 600 },
70+
{ name: "Stack Sans Notch", data: notch("StackSansNotch-Bold.ttf"), weight: 700 },
71+
],
72+
},
73+
);
74+
}

src/app/twitter-image.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// Reuse the same branded card for the Twitter/X preview.
2+
export const runtime = "nodejs";
3+
export { default, alt, size, contentType } from "./opengraph-image";

0 commit comments

Comments
 (0)