From 1f3e674031e4add1816fe61905dc2d6536a175c0 Mon Sep 17 00:00:00 2001 From: Cho Young-Hwi Date: Tue, 24 Mar 2026 20:14:27 +0000 Subject: [PATCH 1/3] [#510] Redesign OG image to match moleskine notebook shape Move title + author inside a portrait moleskine notebook cover (matching StoryCard shape/styling), with metadata (PlotLink branding, genre, plot count, price, plotlink.xyz) outside on the darker background. Adds generous margins to prevent cropping in social previews. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/app/story/[storylineId]/og/route.tsx | 249 +++++++++++++---------- 1 file changed, 139 insertions(+), 110 deletions(-) diff --git a/src/app/story/[storylineId]/og/route.tsx b/src/app/story/[storylineId]/og/route.tsx index 2c2280c0..2875903b 100644 --- a/src/app/story/[storylineId]/og/route.tsx +++ b/src/app/story/[storylineId]/og/route.tsx @@ -14,7 +14,7 @@ async function loadFont(): Promise { // Fetch with no User-Agent → Google returns TTF (truetype) format // ImageResponse supports ttf/otf/woff but NOT woff2 const res = await fetch( - "https://fonts.googleapis.com/css2?family=Lora:wght@700&display=swap", + "https://fonts.googleapis.com/css2?family=Lora:wght@400;700&display=swap", ); const css = await res.text(); const match = @@ -73,7 +73,7 @@ export async function GET( : truncateAddress(sl.writer_address); const plotLabel = sl.plot_count === 1 ? "plot" : "plots"; const titleDisplay = - sl.title.length > 70 ? `${sl.title.slice(0, 67)}...` : sl.title; + sl.title.length > 60 ? `${sl.title.slice(0, 57)}...` : sl.title; const fonts = fontData ? [{ name: "Lora", data: fontData, weight: 700 as const }] @@ -86,40 +86,45 @@ export async function GET( width: "100%", height: "100%", display: "flex", + alignItems: "center", + justifyContent: "center", backgroundColor: "#DDD3C2", - padding: "32px", + padding: "40px 60px", fontFamily: fontData ? "Lora" : "Georgia, serif", }} > - {/* Notebook page */} + {/* Left: Moleskine notebook cover */}
- {/* Red margin line */} + {/* Elastic band */}
- {/* Ruled lines */} + {/* Ruled lines background */}
- {Array.from({ length: 16 }).map((_, i) => ( + {Array.from({ length: 18 }).map((_, i) => (
))}
- {/* Content overlay */} + {/* Content inside notebook: title + author */}
- {/* Top: PlotLink branding */}
35 ? "32px" : "38px", + fontWeight: 700, + color: "#8B4513", + lineHeight: 1.25, display: "flex", - alignItems: "center", - justifyContent: "space-between", + textAlign: "center", + justifyContent: "center", + maxWidth: "290px", }} > -
- PlotLink -
- {sl.genre && ( -
- {sl.genre} -
- )} + {titleDisplay}
- - {/* Center: Story title */}
-
40 ? "42px" : "52px", - fontWeight: 700, - color: "#2C1810", - lineHeight: 1.2, - display: "flex", - }} - > - {titleDisplay} -
-
- by {authorName} -
+ by {authorName}
+
+
- {/* Bottom: metadata bar */} + {/* Right: Metadata on dark background */} +
+ {/* Top: PlotLink branding */} +
+ PlotLink +
+
+ Tokenised collaborative fiction +
+
+ + {/* Middle: genre + stats */} +
+ {sl.genre ? (
- - {sl.plot_count} {plotLabel} - - {priceDisplay && ( - - {priceDisplay} - - )} -
-
- plotlink.xyz + {sl.genre}
+ ) : ( +
+ )} +
+ + {sl.plot_count} {plotLabel} + + {priceDisplay && ( + + {priceDisplay} + + )}
+ + {/* Bottom: domain */} +
+ plotlink.xyz +
), From 4e784d88166d55bfa01fd6e0bd1cc304f76d67ec Mon Sep 17 00:00:00 2001 From: Cho Young-Hwi Date: Tue, 24 Mar 2026 20:16:51 +0000 Subject: [PATCH 2/3] [#510] Revert font URL to wght@700 only Fix regression: requesting both 400;700 weights caused the regex to grab the 400 (regular) URL instead of 700 (bold), making title text render thinner than intended. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/app/story/[storylineId]/og/route.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/story/[storylineId]/og/route.tsx b/src/app/story/[storylineId]/og/route.tsx index 2875903b..96ecfe1d 100644 --- a/src/app/story/[storylineId]/og/route.tsx +++ b/src/app/story/[storylineId]/og/route.tsx @@ -14,7 +14,7 @@ async function loadFont(): Promise { // Fetch with no User-Agent → Google returns TTF (truetype) format // ImageResponse supports ttf/otf/woff but NOT woff2 const res = await fetch( - "https://fonts.googleapis.com/css2?family=Lora:wght@400;700&display=swap", + "https://fonts.googleapis.com/css2?family=Lora:wght@700&display=swap", ); const css = await res.text(); const match = From 273a907ac15e571b48001e95e1dd4012e8e632ef Mon Sep 17 00:00:00 2001 From: Cho Young-Hwi Date: Tue, 24 Mar 2026 20:20:20 +0000 Subject: [PATCH 3/3] [#510] Fix notebook aspect ratio to exact 2:3 matching StoryCard Changed from 370x530 (~0.70) to 350x525 (exactly 2/3) to match the StoryCard's aspect-[2/3] class. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/app/story/[storylineId]/og/route.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/app/story/[storylineId]/og/route.tsx b/src/app/story/[storylineId]/og/route.tsx index 96ecfe1d..1bef4a54 100644 --- a/src/app/story/[storylineId]/og/route.tsx +++ b/src/app/story/[storylineId]/og/route.tsx @@ -96,8 +96,8 @@ export async function GET( {/* Left: Moleskine notebook cover */}