Skip to content

Commit bedc0ef

Browse files
[WIP] Add hero image for social preview in blog posts (#6379)
* Initial plan * fix: use blog hero image for social preview metadata Agent-Logs-Url: https://github.com/feast-dev/feast/sessions/8c33bcc6-0cd4-4222-95a1-bfa02f136b5b Co-authored-by: franciscojavierarceo <4163062+franciscojavierarceo@users.noreply.github.com> * fix: harden hero image extraction for blog social tags Agent-Logs-Url: https://github.com/feast-dev/feast/sessions/8c33bcc6-0cd4-4222-95a1-bfa02f136b5b Co-authored-by: franciscojavierarceo <4163062+franciscojavierarceo@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: franciscojavierarceo <4163062+franciscojavierarceo@users.noreply.github.com>
1 parent f8389fb commit bedc0ef

2 files changed

Lines changed: 38 additions & 7 deletions

File tree

infra/website/src/layouts/BaseLayout.astro

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,17 @@ import '../styles/global.css';
44
interface Props {
55
title: string;
66
description?: string;
7+
socialImage?: string;
8+
ogUrl?: string;
79
}
810
9-
const { title, description = "Feast is an end-to-end open source feature store for machine learning. It allows teams to define, manage, discover, and serve features." } = Astro.props;
11+
const defaultSocialImage = "https://feast.dev/wp-content/uploads/2023/01/feast-og@2x.png";
12+
const {
13+
title,
14+
description = "Feast is an end-to-end open source feature store for machine learning. It allows teams to define, manage, discover, and serve features.",
15+
socialImage = defaultSocialImage,
16+
ogUrl = "https://feast.dev/",
17+
} = Astro.props;
1018
---
1119

1220
<!DOCTYPE html>
@@ -25,16 +33,16 @@ const { title, description = "Feast is an end-to-end open source feature store f
2533
<meta property="og:type" content="website">
2634
<meta property="og:title" content={title}>
2735
<meta property="og:description" content={description}>
28-
<meta property="og:url" content="https://feast.dev/">
36+
<meta property="og:url" content={ogUrl}>
2937
<meta property="og:site_name" content="Feast">
30-
<meta property="og:image" content="https://feast.dev/wp-content/uploads/2023/01/feast-og@2x.png">
38+
<meta property="og:image" content={socialImage}>
3139
<meta property="og:image:width" content="1201">
3240
<meta property="og:image:height" content="630">
3341
<meta property="og:image:type" content="image/png">
3442

3543
<!-- Twitter Card Meta Tags -->
3644
<meta name="twitter:card" content="summary_large_image">
37-
<meta name="twitter:image" content="https://feast.dev/wp-content/uploads/2023/01/feast-og@2x.png">
45+
<meta name="twitter:image" content={socialImage}>
3846

3947
<!-- Fonts -->
4048
<link href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;700&family=IBM+Plex+Sans:wght@400&display=swap" rel="stylesheet">
@@ -51,4 +59,4 @@ const { title, description = "Feast is an end-to-end open source feature store f
5159
</main>
5260
<slot name="footer" />
5361
</body>
54-
</html>
62+
</html>

infra/website/src/pages/blog/[slug].astro

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,25 @@
11
---
22
import BaseLayout from '../../layouts/BaseLayout.astro';
33
import Navigation from '../../components/Navigation.astro';
4+
import { readFileSync } from 'node:fs';
5+
6+
const SITE_URL = 'https://feast.dev';
7+
8+
function toAbsoluteUrl(path: string): string {
9+
if (/^https?:\/\//i.test(path)) {
10+
return path;
11+
}
12+
return new URL(path, SITE_URL).toString();
13+
}
14+
15+
function extractHeroImage(markdown: string): string | undefined {
16+
const heroContainerMatch = markdown.match(/<div[^>]*class=["'][^"']*\bhero-image\b[^"']*["'][^>]*>([\s\S]*?)<\/div>/i);
17+
if (!heroContainerMatch?.[1]) {
18+
return undefined;
19+
}
20+
const imageMatch = heroContainerMatch[1].match(/<img[^>]*\bsrc=["']([^"']+)["'][^>]*>/i);
21+
return imageMatch?.[1];
22+
}
423
524
export async function getStaticPaths() {
625
const posts = await Astro.glob('../../../docs/blog/*.md');
@@ -17,9 +36,13 @@ export async function getStaticPaths() {
1736
1837
const { post } = Astro.props;
1938
const { title, description, date, authors = [] } = post.frontmatter;
39+
const blogUrl = `${SITE_URL}/blog/${Astro.params.slug}/`;
40+
const frontmatterImage = post.frontmatter.hero_image || post.frontmatter.heroImage || post.frontmatter.image;
41+
const heroImage = frontmatterImage || extractHeroImage(readFileSync(post.file, 'utf-8'));
42+
const socialImage = heroImage ? toAbsoluteUrl(heroImage) : undefined;
2043
---
2144

22-
<BaseLayout title={title} description={description}>
45+
<BaseLayout title={title} description={description} socialImage={socialImage} ogUrl={blogUrl}>
2346
<Navigation slot="header" />
2447
<div class="blog-wrapper">
2548
<header class="blog-hero">
@@ -316,4 +339,4 @@ const { title, description, date, authors = [] } = post.frontmatter;
316339
font-size: 18px;
317340
}
318341
}
319-
</style>
342+
</style>

0 commit comments

Comments
 (0)