Skip to content

Commit 770da07

Browse files
committed
docs: generate per-page Open Graph social cards
1 parent cc1c46e commit 770da07

4 files changed

Lines changed: 885 additions & 138 deletions

File tree

docs/.vitepress/config.mts

Lines changed: 91 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,113 @@
11
import { defineConfig } from "vitepress";
2+
import {
3+
describePage,
4+
ogImageOutPath,
5+
ogImageRelPath,
6+
writeOgImage,
7+
type OgPageInfo,
8+
} from "./og-image.mts";
29

310
const repoName = "SimDeck";
411
const githubUrl = `https://github.com/NativeScript/${repoName}`;
512
const siteUrl = "https://simdeck.nativescript.org";
613

14+
type CollectedPage = OgPageInfo & {
15+
slug: string;
16+
urlPath: string;
17+
};
18+
19+
const collectedPages = new Map<string, CollectedPage>();
20+
721
export default defineConfig({
822
title: "SimDeck",
923
description:
1024
"Stream, inspect, and automate iOS Simulators and Android emulators from a browser, CLI, or test.",
1125
lang: "en-US",
1226
cleanUrls: true,
1327
lastUpdated: true,
28+
srcExclude: ["**/public/**"],
1429

1530
head: [
1631
["meta", { name: "theme-color", content: "#0a84ff" }],
1732
["meta", { property: "og:type", content: "website" }],
18-
["meta", { property: "og:title", content: "SimDeck" }],
19-
[
20-
"meta",
21-
{
22-
property: "og:description",
23-
content:
24-
"Stream, inspect, and automate iOS Simulators and Android emulators from a browser, CLI, or test.",
25-
},
26-
],
27-
["meta", { property: "og:url", content: `${siteUrl}/` }],
28-
["link", { rel: "canonical", href: `${siteUrl}/` }],
33+
["meta", { property: "og:site_name", content: "SimDeck" }],
34+
["meta", { name: "twitter:card", content: "summary_large_image" }],
35+
["meta", { name: "twitter:site", content: "@NativeScript" }],
2936
],
3037

38+
transformPageData(pageData) {
39+
if (pageData.relativePath === "404.md") return;
40+
41+
const { slug, urlPath, category } = describePage(pageData.relativePath);
42+
43+
const isHome = pageData.frontmatter.layout === "home";
44+
const hero = (pageData.frontmatter.hero ?? {}) as {
45+
name?: string;
46+
text?: string;
47+
tagline?: string;
48+
};
49+
50+
const title = isHome
51+
? hero.text || hero.name || "SimDeck"
52+
: pageData.title || "SimDeck";
53+
54+
const description =
55+
(pageData.frontmatter.description as string | undefined) ||
56+
(isHome ? hero.tagline : undefined) ||
57+
pageData.description ||
58+
"Stream, inspect, and automate iOS Simulators and Android emulators from a browser, CLI, or test.";
59+
60+
collectedPages.set(slug, {
61+
slug,
62+
urlPath,
63+
title,
64+
description,
65+
category: isHome ? undefined : category,
66+
});
67+
68+
const pageUrl = `${siteUrl}${urlPath}`;
69+
const imageUrl = `${siteUrl}/${ogImageRelPath(slug)}`;
70+
71+
pageData.frontmatter.head ??= [];
72+
pageData.frontmatter.head.push(
73+
["link", { rel: "canonical", href: pageUrl }],
74+
["meta", { property: "og:title", content: title }],
75+
["meta", { property: "og:description", content: description }],
76+
["meta", { property: "og:url", content: pageUrl }],
77+
["meta", { property: "og:image", content: imageUrl }],
78+
["meta", { property: "og:image:width", content: "1200" }],
79+
["meta", { property: "og:image:height", content: "630" }],
80+
["meta", { property: "og:image:alt", content: title }],
81+
["meta", { name: "twitter:title", content: title }],
82+
["meta", { name: "twitter:description", content: description }],
83+
["meta", { name: "twitter:image", content: imageUrl }],
84+
);
85+
},
86+
87+
async buildEnd(siteConfig) {
88+
const outDir = siteConfig.outDir;
89+
if (collectedPages.size === 0) {
90+
console.warn("[og-image] No pages collected; skipping image generation.");
91+
return;
92+
}
93+
94+
const tasks: Array<Promise<void>> = [];
95+
for (const page of collectedPages.values()) {
96+
tasks.push(
97+
writeOgImage(
98+
{
99+
title: page.title,
100+
description: page.description,
101+
category: page.category,
102+
},
103+
ogImageOutPath(outDir, page.slug),
104+
),
105+
);
106+
}
107+
await Promise.all(tasks);
108+
console.log(`[og-image] Generated ${tasks.length} social card images.`);
109+
},
110+
31111
themeConfig: {
32112
siteTitle: "SimDeck",
33113

0 commit comments

Comments
 (0)