Skip to content

Commit c19787b

Browse files
authored
conf: add OG images setup and generate event OG images (graphql#1516)
1 parent 3674316 commit c19787b

File tree

145 files changed

+2023
-91
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

145 files changed

+2023
-91
lines changed

.github/workflows/CI.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ jobs:
1111
with:
1212
node-version: "18.15.0"
1313

14+
- name: Install system dependencies
15+
run: |
16+
sudo apt update
17+
sudo apt-get update
18+
sudo apt-get install libatk-bridge2.0-0
19+
1420
- run: yarn install
1521

1622
- name: Set Sched's API token env

.gitignore

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,11 @@ typings/
5757

5858
# gatsby files
5959
.cache/
60-
public
60+
public/
61+
62+
!static/__og-image/
63+
static/__og-image/*
64+
!static/__og-image/*.png
6165

6266
# Mac files
6367
.DS_Store

gatsby-config.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ const config: GatsbyConfig = {
1414
"gatsby-plugin-postcss",
1515
"gatsby-plugin-svgr",
1616
"gatsby-plugin-anchor-links",
17+
// optional based on env
18+
...(!process.env.GATSBY_CLOUD && !process.env.GITHUB_ACTIONS
19+
? ["gatsby-plugin-dynamic-open-graph-images"]
20+
: []),
1721
{
1822
resolve: "gatsby-source-filesystem",
1923
options: {
@@ -119,7 +123,7 @@ const config: GatsbyConfig = {
119123
],
120124
},
121125
},
122-
],
126+
].filter(Boolean),
123127
}
124128

125129
export default config

gatsby-node.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { ScheduleSession } from "./src/components/Conf/Schedule/ScheduleList"
22
import { SchedSpeaker } from "./src/components/Conf/Speakers/Speaker"
33
import { GatsbyNode } from "gatsby"
4+
import { createOpenGraphImage } from "gatsby-plugin-dynamic-open-graph-images"
45
import * as path from "path"
56
import { glob } from "glob"
67
import _ from "lodash"
@@ -184,6 +185,28 @@ export const createPages: GatsbyNode["createPages"] = async ({
184185
speakers: eventSpeakers,
185186
},
186187
})
188+
189+
if (!process.env.GATSBY_CLOUD && !process.env.GITHUB_ACTIONS) {
190+
try {
191+
createOpenGraphImage(createPage, {
192+
outputDir: "../static/__og-image",
193+
component: path.resolve("./src/templates/EventOgImageTemplate.tsx"),
194+
size: {
195+
width: 1200,
196+
height: 630,
197+
},
198+
waitCondition: "networkidle0",
199+
context: {
200+
id: event.id,
201+
title: event.name,
202+
event,
203+
speakers: eventSpeakers,
204+
},
205+
})
206+
} catch {
207+
console.log("Error creating OG image for", event.name)
208+
}
209+
}
187210
})
188211

189212
// Create speakers list page

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
"date-fns": "^2.30.0",
3030
"gatsby": "5.10.0",
3131
"gatsby-plugin-anchor-links": "1.2.1",
32+
"gatsby-plugin-dynamic-open-graph-images": "^1.1.4",
3233
"gatsby-plugin-feed": "5.10.0",
3334
"gatsby-plugin-google-analytics": "5.10.0",
3435
"gatsby-plugin-less": "7.10.0",

src/components/Conf/Seo/index.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,17 @@ export default function SeoConf(props: {
1313
title?: string
1414
twitterTitle?: string
1515
description?: string
16+
ogImage?: {
17+
url: string
18+
width: number
19+
height: number
20+
}
1621
}) {
1722
const title = props.title ?? defaults.title
1823
const twitterTitle =
1924
props.twitterTitle ?? props.title ?? defaults.twitterTitle
2025
const description = props.description ?? defaults.description
21-
const image = defaults.image
26+
const image = props.ogImage?.url ?? defaults.image
2227

2328
return (
2429
<>
@@ -27,6 +32,7 @@ export default function SeoConf(props: {
2732
<meta property="og:title" content={title} />
2833
<meta property="og:description" content={description} />
2934
<meta property="og:image" content={image} />
35+
<meta property="twitter:image" content={image} />
3036
<meta
3137
property="og:image:alt"
3238
content="GraphQLConf 2023 hosted by the GraphQL Foundation. September 19-21, 2023. San Francisco Bay Area, California"
Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
import React from "react"
2+
import { PageProps } from "gatsby"
3+
import { ScheduleSession } from "../components/Conf/Schedule/ScheduleList"
4+
import { SchedSpeaker } from "../components/Conf/Speakers/Speaker"
5+
import { format, parseISO } from "date-fns"
6+
7+
const EventOgImageTemplate = ({
8+
pageContext,
9+
}: PageProps<{}, { event: ScheduleSession; speakers: SchedSpeaker[] }>) => {
10+
const speakers = pageContext.speakers.map(speaker => ({
11+
name: speaker.name,
12+
avatar: speaker.avatar,
13+
company: speaker.company,
14+
position: speaker.position,
15+
}))
16+
const { name, event_type, event_start: eventDate } = pageContext.event
17+
18+
const eventType = event_type.endsWith("s")
19+
? event_type.slice(0, -1)
20+
: event_type
21+
22+
const eventTitle =
23+
speakers.length > 0
24+
? name.substring(0, name.indexOf(`${speakers[0].name}`) - 3)
25+
: name
26+
27+
return (
28+
<div
29+
style={{
30+
fontFamily: "Rubik, Roboto, sans-serif",
31+
backgroundColor: "black",
32+
backgroundImage:
33+
"linear-gradient(to right, black, black, transparent), url(https://graphql.org/img/conf/graphql-conf-bg.png)",
34+
border: "transparent",
35+
margin: -8,
36+
color: "white",
37+
minHeight: 630,
38+
width: 1200,
39+
display: "flex",
40+
alignItems: "center",
41+
}}
42+
>
43+
<div
44+
style={{
45+
height: "100%",
46+
padding: "82px 105px",
47+
display: "flex",
48+
flexDirection: "column",
49+
justifyContent: "center",
50+
}}
51+
>
52+
<div>
53+
<h1
54+
style={{
55+
display: "flex",
56+
alignItems: "center",
57+
gap: "14px",
58+
color: "white",
59+
paddingTop: 0,
60+
marginTop: 0,
61+
fontSize: "40px",
62+
fontWeight: "bold",
63+
marginBottom: "70px",
64+
}}
65+
>
66+
<span style={{ fontWeight: "bolder" }}>GraphQLConf</span>
67+
<span style={{ fontWeight: "normal" }}>2023</span>
68+
<span
69+
style={{
70+
backgroundColor: "#F5009B",
71+
color: "white",
72+
fontSize: "20px",
73+
fontWeight: "bold",
74+
padding: "18px 20px",
75+
marginLeft: "30px",
76+
alignSelf: "center",
77+
borderRadius: "30px",
78+
}}
79+
>
80+
{eventType.toUpperCase()}
81+
</span>
82+
</h1>
83+
</div>
84+
<div>
85+
<div
86+
style={{
87+
display: "flex",
88+
alignItems: "center",
89+
gap: "35px",
90+
marginBottom: "6px",
91+
fontSize: "22px",
92+
fontStyle: "normal",
93+
fontWeight: 400,
94+
lineHeight: "36px",
95+
color: "white",
96+
}}
97+
>
98+
<span style={{ display: "flex", alignItems: "center" }}>
99+
<svg
100+
style={{ marginRight: "14px", marginBottom: "2px" }}
101+
width="20px"
102+
height="20px"
103+
xmlns="http://www.w3.org/2000/svg"
104+
viewBox="0 0 448 512"
105+
>
106+
{/* <!--! Font Awesome Pro 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --> */}
107+
<path
108+
fill="white"
109+
d="M152 24c0-13.3-10.7-24-24-24s-24 10.7-24 24V64H64C28.7 64 0 92.7 0 128v16 48V448c0 35.3 28.7 64 64 64H384c35.3 0 64-28.7 64-64V192 144 128c0-35.3-28.7-64-64-64H344V24c0-13.3-10.7-24-24-24s-24 10.7-24 24V64H152V24zM48 192H400V448c0 8.8-7.2 16-16 16H64c-8.8 0-16-7.2-16-16V192z"
110+
/>
111+
</svg>
112+
113+
{format(parseISO(eventDate), "EEEE, MMM d")}
114+
</span>
115+
<span style={{ display: "flex", alignItems: "center" }}>
116+
<svg
117+
style={{ marginRight: "14px", marginBottom: "2px" }}
118+
width="20px"
119+
height="20px"
120+
xmlns="http://www.w3.org/2000/svg"
121+
viewBox="0 0 512 512"
122+
>
123+
{/* <!--! Font Awesome Pro 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --> */}
124+
<path
125+
fill="white"
126+
d="M464 256A208 208 0 1 1 48 256a208 208 0 1 1 416 0zM0 256a256 256 0 1 0 512 0A256 256 0 1 0 0 256zM232 120V256c0 8 4 15.5 10.7 20l96 64c11 7.4 25.9 4.4 33.3-6.7s4.4-25.9-6.7-33.3L280 243.2V120c0-13.3-10.7-24-24-24s-24 10.7-24 24z"
127+
/>
128+
</svg>
129+
130+
{format(parseISO(eventDate), "hh:mmaaaa 'PDT'")}
131+
</span>
132+
</div>
133+
134+
<h1
135+
style={{
136+
margin: 0,
137+
padding: 0,
138+
color: "#FFF",
139+
fontSize: "46px",
140+
fontStyle: "normal",
141+
fontWeight: 700,
142+
lineHeight: "64px",
143+
}}
144+
>
145+
{eventTitle}
146+
</h1>
147+
</div>
148+
<div style={{ marginTop: "40px", display: "flex", gap: "20px" }}>
149+
{speakers.map(speaker => (
150+
<div
151+
style={{
152+
display: "flex",
153+
alignItems: "center",
154+
gap: "30px",
155+
}}
156+
>
157+
{speaker.avatar && (
158+
<img
159+
style={{
160+
display: "flex",
161+
alignContent: "center",
162+
justifyItems: "center",
163+
alignItems: "center",
164+
border: "1.5px solid white",
165+
width: "100px",
166+
height: "100px",
167+
borderRadius: "9999px",
168+
marginTop: 0,
169+
marginBottom: 0,
170+
}}
171+
src={speaker.avatar}
172+
alt={speaker.name}
173+
/>
174+
)}
175+
<div
176+
style={{
177+
display: "flex",
178+
flexDirection: "column",
179+
}}
180+
>
181+
<span
182+
style={{
183+
fontWeight: 700,
184+
fontSize: "30px",
185+
lineHeight: "46px",
186+
}}
187+
>
188+
{speaker.name}
189+
</span>
190+
<span
191+
style={{
192+
paddingTop: "7px",
193+
fontSize: "22px",
194+
lineHeight: "36px",
195+
}}
196+
>
197+
{speaker.company}
198+
{speaker.position ? " " + speaker.position : ""}
199+
</span>
200+
</div>
201+
</div>
202+
))}
203+
</div>
204+
</div>
205+
</div>
206+
)
207+
}
208+
209+
export default EventOgImageTemplate

src/templates/event.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,11 @@ export function Head({
207207
<SeoConf
208208
title={`${event.name} | GraphQLConf 2023`}
209209
description={event.description}
210+
ogImage={{
211+
url: `/img/__og-image/${event.id}.png`,
212+
width: 1200,
213+
height: 630,
214+
}}
210215
/>
211216
<meta
212217
name="keywords"
Loading

0 commit comments

Comments
 (0)