mirror of
https://github.com/olehomelchenko/chart-sins.git
synced 2026-08-08 10:32:42 +00:00
Add OpenGraph/Twitter cards, generated per sin at build time
Link previews are the funnel for a "send the link" site, so give every sin a share-optimized card. - og/twitter meta tags on every page (poke as description, canonical URL, summary_large_image) - Per-sin 1200x630 card generated at build: the poke, the before/after charts (uniform height so tall vconcat charts fit), severity meter, category, and short citations — composed with satori, rasterized with @resvg/resvg-js, no browser needed - Default brand card for the homepage and canon - Shared chart pipeline extracted to lib/renderChart.ts (used by both the on-page component and the card generator) - Bundle three IBM Plex TTF weights for the rasterizer Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XPEvmMbac2fCvKXpQcovj8
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
import type { APIRoute, GetStaticPaths } from 'astro';
|
||||
import { getCollection } from 'astro:content';
|
||||
import { getChartSpec } from '../../lib/charts';
|
||||
import { renderSinCard } from '../../lib/og';
|
||||
|
||||
export const getStaticPaths: GetStaticPaths = async () => {
|
||||
const sins = await getCollection('sins', ({ data }) => !data.draft);
|
||||
return sins.map((sin) => ({ params: { slug: sin.id }, props: { sin } }));
|
||||
};
|
||||
|
||||
export const GET: APIRoute = async ({ props }) => {
|
||||
const { sin } = props as { sin: Awaited<ReturnType<typeof getCollection>>[number] };
|
||||
const png = await renderSinCard({
|
||||
poke: sin.data.poke,
|
||||
category: sin.data.category,
|
||||
severity: sin.data.severity,
|
||||
badSpec: getChartSpec(sin.data.badChart),
|
||||
fixedSpec: getChartSpec(sin.data.fixedChart),
|
||||
citationKeys: sin.data.citations.map((c) => c.key),
|
||||
});
|
||||
return new Response(new Uint8Array(png), {
|
||||
headers: { 'Content-Type': 'image/png', 'Cache-Control': 'public, max-age=31536000, immutable' },
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
import type { APIRoute } from 'astro';
|
||||
import { renderDefaultCard } from '../../lib/og';
|
||||
|
||||
export const GET: APIRoute = async () => {
|
||||
const png = await renderDefaultCard();
|
||||
return new Response(new Uint8Array(png), {
|
||||
headers: { 'Content-Type': 'image/png', 'Cache-Control': 'public, max-age=31536000, immutable' },
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user