aboutsummaryrefslogtreecommitdiff
path: root/src/integrations/ogImages.ts
diff options
context:
space:
mode:
authorValentin Popov <valentin@popov.link>2025-06-14 22:25:16 +0300
committerValentin Popov <valentin@popov.link>2025-06-14 22:25:16 +0300
commita81117972d39df35574bbab809bb590abc874761 (patch)
tree41cb25172c7603d2ea0dc275f8d90c72d83bf5a1 /src/integrations/ogImages.ts
parent3d0f4857465e55815809719a4a4438e8a3cd16a0 (diff)
downloadpopov.link-a81117972d39df35574bbab809bb590abc874761.tar.xz
popov.link-a81117972d39df35574bbab809bb590abc874761.zip
feat: implement Open Graph image generation and enhance configuration
- Added ogImages integration to generate Open Graph images for blog posts. - Updated configuration to include Open Graph settings and default preview image. - Refactored Head component to utilize new preview property for Open Graph meta tags. - Enhanced blog post schema to include preview image for structured data representation. - Introduced utility functions for creating Open Graph images with dynamic content.
Diffstat (limited to 'src/integrations/ogImages.ts')
-rw-r--r--src/integrations/ogImages.ts47
1 files changed, 47 insertions, 0 deletions
diff --git a/src/integrations/ogImages.ts b/src/integrations/ogImages.ts
new file mode 100644
index 0000000..5d9146c
--- /dev/null
+++ b/src/integrations/ogImages.ts
@@ -0,0 +1,47 @@
+import type { AstroIntegration } from "astro";
+import { createOgImage } from "../utils/createOgImage";
+import { globby } from "globby";
+import fs from "fs/promises";
+import matter from "gray-matter";
+import path from "path";
+
+const postsDir = path.resolve("./src/content/blog");
+const outDir = path.resolve("./public/images/preview");
+
+export default function ogImageGenerator(): AstroIntegration {
+ return {
+ name: "og-images",
+ hooks: {
+ "astro:build:setup": async ({ logger }) => {
+ await fs.mkdir(outDir, { recursive: true });
+ const mdFiles = await globby("*.md", { cwd: postsDir });
+ logger.info(`${mdFiles.length} posts found`);
+
+ const results = await Promise.allSettled(
+ mdFiles.map(async (file) => {
+ const slug = file.replace(/\.md$/, "");
+ const content = await fs.readFile(path.join(postsDir, file), "utf-8");
+ const { data } = matter(content);
+
+ const png = await createOgImage(data.title, data.datePublished);
+ const outPath = path.join(outDir, `${slug}.png`);
+ await fs.writeFile(outPath, png);
+
+ logger.info(`OG image created: ${slug}`);
+ })
+ );
+
+ results.forEach((r) => {
+ if (r.status === "rejected") {
+ logger.error(`Error for ${r.reason.slug}: ${r.reason.message}`);
+ }
+ });
+
+ const failures = results.filter((r) => r.status === "rejected");
+ if (failures.length) {
+ throw new Error(`Failed to generate OG images for ${failures.length} posts`);
+ }
+ },
+ },
+ };
+}