diff --git a/src/og/ogImage.ts b/src/og/ogImage.ts index dff88a6..a8419fa 100644 --- a/src/og/ogImage.ts +++ b/src/og/ogImage.ts @@ -15,6 +15,10 @@ export function computeOgPath(pathname: string): string { if (clean === '/speakers') return '/og/pages/speakers.png' if (clean === '/' || clean === '') return '/og/default.png' if (clean.startsWith('/schedule')) return '/og/pages/schedule.png' + if (clean === '/blog') return '/og/pages/blog.png' + // Individual /blog/ articles pass an explicit metaImage (see + // src/pages/blog/[...slug].astro); a stray unknown /blog/* route falls + // back to default. if (clean.startsWith('/blog')) return '/og/default.png' const staticPages = ['team', 'jobs', 'location', 'anecdotes', 'jeu', 'coc', '404'] const seg = clean.replace(/^\//, '').split('/')[0] diff --git a/src/pages/blog/[...slug].astro b/src/pages/blog/[...slug].astro index 70b7863..647ff79 100644 --- a/src/pages/blog/[...slug].astro +++ b/src/pages/blog/[...slug].astro @@ -14,9 +14,13 @@ export async function getStaticPaths() { const { entry } = Astro.props const { Content } = await render(entry) +const ogImage = `${import.meta.env.SITE}/og/blog/${entry.id}.png` --- - + diff --git a/src/pages/og/blog/[slug].png.ts b/src/pages/og/blog/[slug].png.ts new file mode 100644 index 0000000..7e23f29 --- /dev/null +++ b/src/pages/og/blog/[slug].png.ts @@ -0,0 +1,52 @@ +import { createHash } from 'node:crypto' +import type { APIRoute } from 'astro' +import { getCollection } from 'astro:content' +import { + getFlamingoDataUri, + getMonochromeLogoDataUri, + pngResponse, + readOgCache, + renderOg, + writeOgCache, +} from '../../../og/render' +import { pageTemplate } from '../../../og/templates' + +export async function getStaticPaths() { + const entries = await getCollection('blog') + return entries.map((entry) => ({ + params: { slug: entry.id }, + props: { + title: entry.data.title, + date: entry.data.date.toISOString(), + }, + })) +} + +export const GET: APIRoute = async ({ params, props }) => { + const contentHash = createHash('sha256') + .update(props.title + props.date) + .digest('hex') + .slice(0, 8) + const cacheKey = `blog/${params.slug}-${contentHash}.png` + const cached = await readOgCache(cacheKey) + if (cached) return pngResponse(cached) + + const [logo, flamingo] = await Promise.all([getMonochromeLogoDataUri(), getFlamingoDataUri()]) + const date = new Date(props.date).toLocaleDateString('fr-FR', { + day: 'numeric', + month: 'long', + year: 'numeric', + }) + const png = await renderOg( + pageTemplate( + logo, + { + eyebrow: `Blog · ${date}`, + title: props.title, + }, + flamingo + ) + ) + await writeOgCache(cacheKey, png) + return pngResponse(png) +} diff --git a/src/pages/og/pages/[page].png.ts b/src/pages/og/pages/[page].png.ts index 8ed03f6..b2e156f 100644 --- a/src/pages/og/pages/[page].png.ts +++ b/src/pages/og/pages/[page].png.ts @@ -55,6 +55,11 @@ const PAGES: Record = { title: 'Code de conduite', description: 'Une conférence respectueuse, inclusive et bienveillante pour tou·te·s.', }, + blog: { + eyebrow: 'Blog', + title: 'Blog', + description: "Coulisses, chiffres et décisions de l'équipe Sunny Tech.", + }, '404': { eyebrow: 'Erreur 404', title: 'Page introuvable',