Skip to content

Commit cf23c4c

Browse files
committed
Make session OG image work
1 parent 89677bd commit cf23c4c

File tree

6 files changed

+197
-73
lines changed

6 files changed

+197
-73
lines changed

src/app/(development)/workroom/page.tsx

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import SpeakerOpengraphImage from "@/app/conf/2025/components/speaker-opengraph-image"
2-
import ScheduleOpengraphImage from "@/app/conf/2025/components/session-opengraph-image"
1+
import { SpeakerOpengraphImage } from "@/app/conf/2025/components/speaker-opengraph-image"
2+
import { SessionOpengraphImage } from "@/app/conf/2025/components/session-opengraph-image"
33
import { SchedSpeaker } from "@/app/conf/2023/types"
44

55
// todo: the images probably won't work after conversion
@@ -45,43 +45,46 @@ export default function WorkroomPage() {
4545
/>
4646

4747
<p>ScheduleOpengraphImage / no speakers</p>
48-
<ScheduleOpengraphImage
48+
<SessionOpengraphImage
4949
session={{
5050
name: "Welcome & Opening Remarks",
5151
speakers: [],
5252
event_type: "",
53+
event_subtype: "",
5354
}}
5455
date="September 8-10"
5556
year="2025"
5657
location="Amsterdam, Netherlands"
5758
/>
5859

5960
<p>ScheduleOpengraphImage / single speaker</p>
60-
<ScheduleOpengraphImage
61+
<SessionOpengraphImage
6162
session={{
6263
name: "The State of Distributed GraphQL",
6364
speakers: [enisdenjo],
6465
event_type: "Keynote Sessions",
66+
event_subtype: "",
6567
}}
6668
date="September 8-10"
6769
year="2025"
6870
location="Amsterdam, Netherlands"
6971
/>
7072

7173
<p>ScheduleOpengraphImage / multiple speakers</p>
72-
<ScheduleOpengraphImage
74+
<SessionOpengraphImage
7375
session={{
7476
name: "TSC Panel",
7577
speakers: [enisdenjo, saihaj],
76-
event_type: "Keynote Sessions",
78+
event_type: "Developer Experience",
79+
event_subtype: "Backend",
7780
}}
7881
date="September 8-10"
7982
year="2025"
8083
location="Amsterdam, Netherlands"
8184
/>
8285

8386
<p>SpeakerOpengraphImage / very long title</p>
84-
<ScheduleOpengraphImage
87+
<SessionOpengraphImage
8588
session={{
8689
name: "TSC Panel - Lee Byron, GraphQL Foundation; Kewei Qu, Meta; Rob Richard, 1stDibs; Michael Staib, ChilliCream; Moderated by Sasha Solomon, Staff Software Engineer & Tech Lead",
8790
speakers: [
@@ -104,6 +107,7 @@ export default function WorkroomPage() {
104107
{ ...enisdenjo, name: "Sasha Solomon" },
105108
],
106109
event_type: "Keynote Sessions",
110+
event_subtype: "",
107111
}}
108112
date="September 8-10"
109113
year="2025"

src/app/conf/2025/components/session-opengraph-image.tsx

Lines changed: 123 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,20 @@ import type { SchedSpeaker } from "@/app/conf/2023/types"
33
import {
44
ConferenceOpengraphImageHeader,
55
normalizeProtocolRelativeUrl,
6+
colors,
7+
OpengraphImageFooter,
8+
fonts,
69
} from "./speaker-opengraph-image"
710
import { getEventTitle } from "../utils"
811
import { formatSpeakerPosition } from "./format-speaker-position"
12+
import { speakers as allSpeakers } from "../_data"
913

10-
interface ScheduleOpengraphImageProps
14+
export interface SessionOpengraphImageProps
1115
extends React.HTMLAttributes<HTMLElement> {
12-
session: Pick<ScheduleSession, "name" | "speakers" | "event_type">
16+
session: Pick<
17+
ScheduleSession,
18+
"name" | "speakers" | "event_type" | "event_subtype"
19+
>
1320
date: string
1421
year: string
1522
location: string
@@ -19,19 +26,23 @@ function isString(x: unknown): x is string {
1926
return Object.prototype.toString.call(x) === "[object String]"
2027
}
2128

22-
export default function ScheduleOpengraphImage({
29+
export function SessionOpengraphImage({
2330
session,
2431
date,
2532
location,
2633
year,
2734
...rest
28-
}: ScheduleOpengraphImageProps) {
35+
}: SessionOpengraphImageProps) {
2936
const speakers = session.speakers
3037
? isString(session.speakers)
3138
? (session.speakers as string)
3239
.split(",")
3340
.map(name => ({ name, username: "", avatar: "" }))
34-
: (session.speakers as SchedSpeaker[])
41+
: session.speakers.map(speaker => {
42+
return (
43+
allSpeakers.find(s => s.username === speaker.username) || speaker
44+
)
45+
})
3546
: []
3647

3748
const eventTitle = getEventTitle(
@@ -41,7 +52,17 @@ export default function ScheduleOpengraphImage({
4152

4253
return (
4354
<article
44-
className="flex h-[630px] w-[1200px] flex-col overflow-hidden border-2 border-neu-300 bg-neu-100"
55+
style={{
56+
display: "flex",
57+
height: "630px",
58+
width: "1200px",
59+
flexDirection: "column",
60+
overflow: "hidden",
61+
borderWidth: "2px",
62+
borderColor: colors.neu600,
63+
backgroundColor: colors.neu100,
64+
fontFamily: fonts.sans,
65+
}}
4566
{...rest}
4667
>
4768
<ConferenceOpengraphImageHeader
@@ -50,11 +71,28 @@ export default function ScheduleOpengraphImage({
5071
location={location}
5172
/>
5273

53-
<div className="flex flex-1 flex-col justify-between p-10">
54-
<div className="flex flex-col gap-10">
74+
<div
75+
style={{
76+
display: "flex",
77+
flex: 1,
78+
flexDirection: "column",
79+
justifyContent: "space-between",
80+
padding: "2.5rem",
81+
}}
82+
>
83+
<div
84+
style={{
85+
display: "flex",
86+
flexDirection: "column",
87+
gap: "2.5rem",
88+
}}
89+
>
5590
<h3
56-
className="m-0 font-sans leading-tight text-neu-900"
5791
style={{
92+
margin: 0,
93+
fontFamily: fonts.sans,
94+
lineHeight: "1.25",
95+
color: colors.neu900,
5896
fontSize: eventTitle.length <= 32 ? "72px" : "32px",
5997
}}
6098
>
@@ -63,25 +101,76 @@ export default function ScheduleOpengraphImage({
63101
</div>
64102

65103
{speakers.length === 1 && speakers[0] && (
66-
<div className="flex items-center gap-10">
104+
<div
105+
style={{
106+
display: "flex",
107+
alignItems: "flex-end",
108+
gap: "2.5rem",
109+
}}
110+
>
67111
{speakers[0]?.avatar && (
68-
<div className="relative overflow-hidden">
69-
<div className="absolute inset-0 z-[1] bg-sec-lighter mix-blend-multiply" />
112+
<div
113+
style={{
114+
position: "relative",
115+
overflow: "hidden",
116+
display: "flex",
117+
}}
118+
>
70119
<img
71120
src={normalizeProtocolRelativeUrl(speakers[0].avatar)}
72121
alt=""
73-
className="size-[120px] object-cover"
122+
style={{
123+
width: "120px",
124+
height: "120px",
125+
objectFit: "cover",
126+
filter: "sepia(1) hue-rotate(37.5deg)",
127+
}}
74128
width={120}
75129
height={120}
76130
/>
131+
<div
132+
style={{
133+
position: "absolute",
134+
top: 0,
135+
left: 0,
136+
width: "120px",
137+
height: "120px",
138+
backgroundColor: colors.secLighter,
139+
opacity: 0.25,
140+
}}
141+
/>
77142
</div>
78143
)}
79-
<div className="flex flex-col gap-4">
80-
<h4 className="m-0 font-sans text-[48px] font-normal leading-tight text-neu-900">
144+
<div
145+
style={{
146+
display: "flex",
147+
flexDirection: "column",
148+
justifyContent: "flex-end",
149+
gap: "1rem",
150+
}}
151+
>
152+
<h4
153+
style={{
154+
margin: 0,
155+
fontFamily: fonts.sans,
156+
fontSize: "48px",
157+
fontWeight: "normal",
158+
lineHeight: "1",
159+
color: colors.neu900,
160+
}}
161+
>
81162
{speakers[0].name}
82163
</h4>
83164
{"company" in speakers[0] && speakers[0].company && (
84-
<span className="font-sans text-[32px] font-normal leading-tight text-neu-700">
165+
<span
166+
style={{
167+
fontFamily: fonts.sans,
168+
fontSize: "32px",
169+
fontWeight: "normal",
170+
lineHeight: "1",
171+
color: colors.neu700,
172+
}}
173+
>
85174
{formatSpeakerPosition(speakers[0] as SchedSpeaker)}
86175
</span>
87176
)}
@@ -90,10 +179,20 @@ export default function ScheduleOpengraphImage({
90179
)}
91180

92181
{speakers.length > 1 && (
93-
<div className="flex flex-col gap-4">
182+
<div
183+
style={{
184+
display: "flex",
185+
flexDirection: "column",
186+
gap: "1rem",
187+
}}
188+
>
94189
<h4
95-
className="m-0 font-sans font-normal leading-tight text-neu-900"
96190
style={{
191+
margin: 0,
192+
fontFamily: fonts.sans,
193+
fontWeight: "normal",
194+
lineHeight: "1.25",
195+
color: colors.neu900,
97196
fontSize: speakers.length < 4 ? "48px" : "32px",
98197
}}
99198
>
@@ -103,12 +202,12 @@ export default function ScheduleOpengraphImage({
103202
)}
104203
</div>
105204

106-
{session.event_type && (
107-
<footer className="flex items-center border-t-2 border-neu-300 px-16 py-8 pl-10">
108-
<span className="font-mono text-2xl font-normal uppercase leading-none text-neu-900">
109-
{session.event_type}
110-
</span>
111-
</footer>
205+
{(session.event_type || session.event_subtype) && (
206+
<OpengraphImageFooter>
207+
{[session.event_type, session.event_subtype]
208+
.filter(Boolean)
209+
.join(" — ")}
210+
</OpengraphImageFooter>
112211
)}
113212
</article>
114213
)

0 commit comments

Comments
 (0)