Skip to content

Commit ee7043f

Browse files
philhawksworththisisjofrankjosh-collinsworth
authored
Generate OG images for each page (#1527)
Co-authored-by: Jo Franchetti <jofranchetti@gmail.com> Co-authored-by: Josh Collinsworth <joshuajcollinsworth@gmail.com>
1 parent d057c55 commit ee7043f

File tree

147 files changed

+789
-56
lines changed

Some content is hidden

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

147 files changed

+789
-56
lines changed

README.md

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,18 @@ deno task prod
3131
Which will start a Deno server on [localhost:8000](http://localhost:8000) used
3232
in production, which handles redirects.
3333

34+
the above commands will defauilt to performing as complete build of the site
35+
including all of the more expensive operations. You can also perform a lighter
36+
build by running:
37+
38+
```console
39+
deno task build:light
40+
```
41+
42+
This will build the site without generating the Open Graph images and other more
43+
time-consuming operations which might be desirable to skip during local
44+
developement work.
45+
3446
## Developing styles and components
3547

3648
We are increasingly making use of global components to improve consistency and
@@ -39,10 +51,10 @@ components and is generated during the build process.
3951

4052
You can browse to it in the site at `/styleguide/`
4153

42-
To avoid longer build times of rthe sntire site and all of its content while
43-
developing UI elements and components, a styulguide-only build is avaiable which
54+
To avoid longer build times of the entire site and all of its content while
55+
developing UI elements and components, a styleguide-only build is avaiable which
4456
performs the initial global configureation for the site, but then only generates
45-
and wacthes for changes in the `/styleguide` folder of the repo.
57+
and watches for changes in the `/styleguide` folder of the repo.
4658

4759
To work on just the components and UI elements and review them within
4860
styleguide, run:

_components/OpenGraph.tsx

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
export default function OpenGraph(
2+
{ title, description, section, url }: {
3+
title: string;
4+
description: string;
5+
section: string;
6+
url: string;
7+
},
8+
) {
9+
let image;
10+
if (section == "api") {
11+
image = `/img/og.webp`;
12+
} else {
13+
image = `${url}index.png`;
14+
}
15+
return (
16+
<>
17+
<meta name="twitter:title" content={title} />
18+
<meta name="twitter:description" content={description} />
19+
<meta name="twitter:image" content={image} />
20+
<meta name="twitter:image:alt" content={description} />
21+
<meta name="twitter:card" content="summary_large_image" />
22+
<meta name="twitter:site" content="@deno_land" />
23+
<meta property="og:title" content={title} />
24+
<meta property="og:description" content={description} />
25+
<meta property="og:image" content={image} />
26+
<meta property="og:image:alt" content={description} />
27+
<meta property="og:type" content="article" />
28+
<meta property="og:site_name" content="Deno" />
29+
<meta property="og:locale" content="en_US" />
30+
</>
31+
);
32+
}

_config-styleguide.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Further refine the global Lume config for this section of the site
22
import site from "./_config.ts";
33

4-
// Ignore everythig not in the styleguide folder
4+
// Ignore everything not in the styleguide folder
55
site.ignore((path) => {
66
return path.match(/^\/styleguide.*$/) === null;
77
});

_config.ts

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import lume from "lume/mod.ts";
44
import esbuild from "lume/plugins/esbuild.ts";
55
import jsx from "lume/plugins/jsx_preact.ts";
66
import mdx from "lume/plugins/mdx.ts";
7+
import ogImages from "lume/plugins/og_images.ts";
78
import postcss from "lume/plugins/postcss.ts";
89
import redirects from "lume/plugins/redirects.ts";
910
import search from "lume/plugins/search.ts";
@@ -17,6 +18,7 @@ import Prism from "./prism.ts";
1718
import title from "https://deno.land/x/lume_markdown_plugins@v0.7.0/title.ts";
1819
import toc from "https://deno.land/x/lume_markdown_plugins@v0.7.0/toc.ts";
1920
import { CSS as GFM_CSS } from "https://jsr.io/@deno/gfm/0.8.2/style.ts";
21+
import { log } from "lume/core/utils/log.ts";
2022
import anchor from "npm:markdown-it-anchor@9";
2123
import { full as emoji } from "npm:markdown-it-emoji@3";
2224
import admonitionPlugin from "./markdown-it/admonition.ts";
@@ -31,7 +33,6 @@ import redirectsMiddleware, {
3133
toFileAndInMemory,
3234
} from "./middleware/redirects.ts";
3335
import { cliNow } from "./timeUtils.ts";
34-
import { log } from "lume/core/utils/log.ts";
3536

3637
const site = lume(
3738
{
@@ -186,6 +187,48 @@ site.ignore(
186187
// the default layout if no other layout is specified
187188
site.data("layout", "doc.tsx");
188189

190+
// Do more expensive operations if we're building the full site
191+
if (Deno.env.get("BUILD_TYPE") == "FULL") {
192+
// Use Lume's built in date function to get the last modified date of the file
193+
// site.data("date", "Git Last Modified");;
194+
195+
// Generate Open Graph images
196+
site.data("openGraphLayout", "/open_graph/default.jsx");
197+
site.data("openGraphColor", "#70ffaf");
198+
site.use(ogImages({
199+
satori: {
200+
width: 1200,
201+
height: 630,
202+
fonts: [
203+
{
204+
name: "Courier",
205+
style: "normal",
206+
data: await Deno.readFile(
207+
"./static/fonts/courier/CourierPrime-Regular.ttf",
208+
),
209+
},
210+
{
211+
name: "Inter",
212+
weight: 400,
213+
style: "normal",
214+
data: await Deno.readFile(
215+
"./static/fonts/inter/Inter-Regular.woff",
216+
),
217+
},
218+
{
219+
name: "Inter",
220+
weight: 700,
221+
style: "bold",
222+
data: await Deno.readFile(
223+
"./static/fonts/inter/Inter-SemiBold.woff",
224+
),
225+
},
226+
],
227+
},
228+
cache: false,
229+
}));
230+
}
231+
189232
site.scopedUpdates(
190233
(path) => path == "/overrides.css",
191234
(path) => /\.(js|ts)$/.test(path),

_includes/doc.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ import renderCommand from "./renderCommand.tsx";
22

33
export const layout = "layout.tsx";
44

5+
export const ogImage = (data: Lume.Data) => {
6+
return data.url + "/index.png";
7+
};
8+
59
export default function Doc(data: Lume.Data, helpers: Lume.Helpers) {
610
let file = data.page.sourcePath;
711

_includes/layout.tsx

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -25,37 +25,17 @@ export default function Layout(data: Lume.Data) {
2525
type="font/woff2"
2626
crossOrigin="true"
2727
/>
28-
29-
<meta name="twitter:card" content="summary_large_image" />
30-
<meta name="twitter:site" content="@deno_land" />
3128
<link rel="me" href="https://fosstodon.org/@deno_land" />
32-
<meta name="twitter:title" content={data.title} />
33-
<meta property="og:title" content={data.title} />
34-
35-
<meta property="og:description" content={description} />
36-
<meta name="twitter:description" content={description} />
37-
<meta name="description" content={description} />
38-
39-
<meta name="twitter:image" content="/img/og.webp" />
40-
<meta
41-
name="twitter:image:alt"
42-
content="Deno docs: Deno documentation, guides, and reference materials. docs.deno.com"
29+
<data.comp.OpenGraph
30+
title={data.title}
31+
description={description}
32+
section={section}
33+
url={data.url}
4334
/>
44-
<meta property="og:image" content="/img/og.webp" />
45-
<meta
46-
property="og:image:alt"
47-
content="Deno docs: Deno documentation, guides, and reference materials. docs.deno.com"
48-
/>
49-
50-
<meta property="og:type" content="article" />
51-
<meta property="og:site_name" content="Deno" />
52-
<meta property="og:locale" content="en_US" />
53-
5435
<meta
5536
name="keywords"
5637
content="Deno, JavaScript, TypeScript, reference, documentation, guide, tutorial, example"
5738
/>
58-
5939
<script
6040
dangerouslySetInnerHTML={{
6141
__html: `

_includes/open_graph/cli-commands.jsx

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/** @jsxImportSource npm:react@18.2.0 */
2+
3+
export default function ({ title, description, openGraphTitle }) {
4+
if (!openGraphTitle) {
5+
title = "deno help";
6+
}
7+
if (!description) {
8+
description = "Learn more at docs.deno.com";
9+
}
10+
11+
return (
12+
<div
13+
style={{
14+
height: "100%",
15+
width: "100%",
16+
display: "flex",
17+
flexDirection: "column",
18+
justifyContent: "center",
19+
background:
20+
`radial-gradient(circle at 95% 95%, #090909 10%, #292929 70%)`,
21+
fontSize: 28,
22+
fontWeight: 400,
23+
padding: "0 90px",
24+
textWrap: "balance",
25+
color: "#fff",
26+
fontFamily: "Inter",
27+
}}
28+
>
29+
<p
30+
style={{
31+
fontSize: "18px",
32+
lineHeight: "1",
33+
marginBottom: "2rem",
34+
textTransform: "uppercase",
35+
}}
36+
>
37+
docs.deno.com
38+
</p>
39+
<h1
40+
style={{
41+
margin: "0",
42+
fontSize: 60,
43+
fontWeight: 800,
44+
lineHeight: "1.1",
45+
marginTop: 0,
46+
marginLeft: "-16px",
47+
marginBottom: "2rem",
48+
}}
49+
>
50+
<span
51+
style={{
52+
background: "#000",
53+
borderRadius: "10px",
54+
padding: "10px 18px 4px 18px",
55+
fontFamily: "Courier",
56+
lineHeight: "1.2",
57+
color: "#ffffff",
58+
textShadow: "0 0 8px #70ffafff",
59+
}}
60+
>
61+
{openGraphTitle}
62+
</span>
63+
</h1>
64+
<p
65+
style={{
66+
marginTop: 0,
67+
width: "72%",
68+
lineHeight: "1.5",
69+
}}
70+
>
71+
{description}
72+
</p>
73+
<svg
74+
xmlns="http://www.w3.org/2000/svg"
75+
viewBox="0 0 401 401"
76+
fill-rule="evenodd"
77+
style={{
78+
position: "absolute",
79+
bottom: "2rem",
80+
right: "2rem",
81+
width: "80px",
82+
height: "80px",
83+
}}
84+
>
85+
<path
86+
fill="#ffffff"
87+
d="M261.684 245.149c33.861 1.662 69.225-13.535 80.203-43.776 10.978-30.241 6.721-60.148-32.661-78.086-39.381-17.944-57.569-39.272-89.385-52.14-20.787-8.408-43.915-3.418-67.664 9.707-63.963 35.351-121.274 147.038-94.858 250.518a3.185 3.185 0 0 1-1.544 3.615 3.189 3.189 0 0 1-3.877-.64C16.282 295.06-3.759 241.788.593 184.791 8.998 74.728 105.178-7.806 215.241.599 325.296 9.003 407.83 105.182 399.425 215.245c-3.529 46.221-22.535 87.584-51.559 119.399-22.195 22.8-50.473 32.935-74.07 32.516-17.107-.303-33.839-7.112-45.409-17.066-16.516-14.228-23.191-30.485-25.474-48.635-.572-4.507-.236-16.797 2.112-25.309 1.745-6.343 6.185-18.599 12.676-23.957-7.595-3.266-17.361-10.388-20.446-13.805-.753-.838-.652-2.156.026-3.057a2.56 2.56 0 0 1 2.925-.88c6.528 2.239 14.477 4.444 22.86 5.851 11.021 1.844 24.729 4.159 38.618 4.847ZM192.777 85.086c10.789-.846 20.202 8.363 21.825 20.609 2.164 16.314-3.822 33.166-23.511 33.554-16.819.335-21.915-16.625-20.8-26.9 1.107-10.275 9.577-26.25 22.486-27.263Z"
88+
/>
89+
</svg>
90+
</div>
91+
);
92+
}

_includes/open_graph/default.jsx

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/** @jsxImportSource npm:react@18.2.0 */
2+
3+
export default function ({ title, description, openGraphColor }) {
4+
if (!title) {
5+
title = "Deno documentation";
6+
}
7+
if (!description) {
8+
description = "Learn more at docs.deno.com";
9+
}
10+
11+
const bgColor = openGraphColor || "#70ffaf";
12+
13+
return (
14+
<div
15+
style={{
16+
height: "100%",
17+
width: "100%",
18+
display: "flex",
19+
position: "relative",
20+
flexDirection: "column",
21+
justifyContent: "center",
22+
padding: "0 90px",
23+
fontSize: 26,
24+
fontWeight: 400,
25+
textWrap: "balance",
26+
background:
27+
`radial-gradient(circle at 98% 98%, #ffffff 12%, ${bgColor} 70%)`,
28+
fontFamily: "Inter",
29+
}}
30+
>
31+
<p
32+
style={{
33+
fontSize: "18px",
34+
lineHeight: "1",
35+
marginBottom: "2rem",
36+
textTransform: "uppercase",
37+
}}
38+
>
39+
docs.deno.com
40+
</p>
41+
<h1
42+
style={{
43+
margin: "0",
44+
fontSize: 60,
45+
fontWeight: 800,
46+
width: "100%",
47+
lineHeight: "1.1",
48+
marginTop: 0,
49+
}}
50+
>
51+
{title}
52+
</h1>
53+
<div
54+
style={{
55+
width: "400px",
56+
height: "1px",
57+
margin: "3rem 0",
58+
background: "#000",
59+
}}
60+
>
61+
</div>
62+
<p
63+
style={{
64+
marginTop: 0,
65+
width: "72%",
66+
lineHeight: "1.5",
67+
}}
68+
>
69+
{description}
70+
</p>
71+
<svg
72+
xmlns="http://www.w3.org/2000/svg"
73+
viewBox="0 0 401 401"
74+
fill-rule="evenodd"
75+
style={{
76+
position: "absolute",
77+
bottom: "2rem",
78+
right: "2rem",
79+
width: "80px",
80+
height: "80px",
81+
}}
82+
>
83+
<path d="M261.684 245.149c33.861 1.662 69.225-13.535 80.203-43.776 10.978-30.241 6.721-60.148-32.661-78.086-39.381-17.944-57.569-39.272-89.385-52.14-20.787-8.408-43.915-3.418-67.664 9.707-63.963 35.351-121.274 147.038-94.858 250.518a3.185 3.185 0 0 1-1.544 3.615 3.189 3.189 0 0 1-3.877-.64C16.282 295.06-3.759 241.788.593 184.791 8.998 74.728 105.178-7.806 215.241.599 325.296 9.003 407.83 105.182 399.425 215.245c-3.529 46.221-22.535 87.584-51.559 119.399-22.195 22.8-50.473 32.935-74.07 32.516-17.107-.303-33.839-7.112-45.409-17.066-16.516-14.228-23.191-30.485-25.474-48.635-.572-4.507-.236-16.797 2.112-25.309 1.745-6.343 6.185-18.599 12.676-23.957-7.595-3.266-17.361-10.388-20.446-13.805-.753-.838-.652-2.156.026-3.057a2.56 2.56 0 0 1 2.925-.88c6.528 2.239 14.477 4.444 22.86 5.851 11.021 1.844 24.729 4.159 38.618 4.847ZM192.777 85.086c10.789-.846 20.202 8.363 21.825 20.609 2.164 16.314-3.822 33.166-23.511 33.554-16.819.335-21.915-16.625-20.8-26.9 1.107-10.275 9.577-26.25 22.486-27.263Z" />
84+
</svg>
85+
</div>
86+
);
87+
}

0 commit comments

Comments
 (0)