Skip to content

Instantly share code, notes, and snippets.

@mdichtler
Created April 19, 2026 10:18
Show Gist options
  • Select an option

  • Save mdichtler/c15c538383347d8c46b8ebe286e93ac6 to your computer and use it in GitHub Desktop.

Select an option

Save mdichtler/c15c538383347d8c46b8ebe286e93ac6 to your computer and use it in GitHub Desktop.
behindthe.dev - Dynamic Image Endpoint
import satori from 'satori';
import { Resvg } from '@resvg/resvg-js';
import { getCollection } from 'astro:content';
import { readFileSync } from 'node:fs';
import path from 'node:path';
export async function getStaticPaths() {
const posts = await getCollection('blog');
const paths = [];
for (const post of posts) {
const slug = post.id.replace(/\.[^/.]+$/, '');
paths.push({ params: { slug }, props: { post, isThumb: false } });
paths.push({ params: { slug: `thumb-${slug}` }, props: { post, isThumb: true } });
}
// handle non blog pages overwrites
const extraPages = [
{ slug: 'default', title: 'behindthe.dev | Goats & Engineering', tags: ['dev'] },
{ slug: 'about', title: 'About | Martin Dichtler', tags: ['bio'] },
{ slug: 'terms', title: 'Terms of Service | behindthe.dev', tags: ['legal'] },
{ slug: 'privacy', title: 'Privacy Policy | behindthe.dev', tags: ['legal'] },
];
for (const page of extraPages) {
const postMock = { data: { title: page.title, tags: page.tags } };
paths.push({ params: { slug: page.slug }, props: { post: postMock, isThumb: false } });
paths.push({ params: { slug: `thumb-${page.slug}` }, props: { post: postMock, isThumb: true } });
}
return paths;
}
export async function GET({ props }: { props: { post: any; isThumb: boolean } }) {
const { post, isThumb } = props;
const title = post.data.title;
const tag = (post.data.tags?.[0] || 'dev').toLowerCase();
// Color palette for categories
const palettes: Record<string, { bg: string; accent: string; secondary: string }> = {
// Add new categories / palettes that will be inserted based on markdown tags
default: { bg: '#0b1120', accent: '#38bdf8', secondary: '#0ea5e9' },
};
const { bg, accent, secondary } = palettes[tag] || palettes.default;
const noiseFilter = `
<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'>
<filter id='n'>
<feTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='3' stitchTiles='stitch'/>
<feColorMatrix type='saturate' values='0'/>
</filter>
<rect width='100%' height='100%' filter='url(#n)' opacity='0.15'/>
</svg>
`;
const noiseDataUri = `data:image/svg+xml;base64,${Buffer.from(noiseFilter).toString('base64')}`;
// fonts
const boldFont = readFileSync(path.join(process.cwd(), 'public/fonts/atkinson-bold.woff'));
const semiBoldFont = readFileSync(path.join(process.cwd(), 'public/fonts/atkinson-bold.woff'));
const svg = await satori(
{
type: 'div',
props: {
style: {
height: '100%',
width: '100%',
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
padding: '80px',
backgroundColor: bg,
backgroundImage: `radial-gradient(circle at 100% 0%, ${accent}33, transparent), radial-gradient(circle at 0% 100%, ${secondary}22, transparent)`,
color: 'white',
fontFamily: 'Atkinson',
position: 'relative',
overflow: 'hidden',
},
children: [
// The "Grainy" layer
{
type: 'div',
props: {
style: {
position: 'absolute',
inset: 0,
backgroundImage: `url(${noiseDataUri})`,
opacity: 0.25,
backgroundRepeat: 'repeat',
},
},
},
// Accent line
{
type: 'div',
props: {
style: {
position: 'absolute',
top: 0,
left: 0,
height: '8px',
width: '100%',
background: `linear-gradient(to right, ${accent}, ${secondary})`,
},
},
},
// Branding Header
{
type: 'div',
props: {
style: {
position: 'absolute',
top: '60px',
left: '80px',
display: 'flex',
alignItems: 'center',
gap: '12px',
},
children: [
{
type: 'div',
props: {
style: {
width: '24px',
height: '24px',
borderRadius: '6px',
backgroundColor: accent,
}
}
},
{
type: 'div',
props: {
style: {
fontSize: '28px',
fontWeight: '800',
letterSpacing: '-0.02em',
opacity: 0.8,
},
children: 'behindthe.dev',
},
}
]
},
},
// Tag badge
{
type: 'div',
props: {
style: {
fontSize: '24px',
fontWeight: '600',
marginBottom: '16px',
color: accent,
textTransform: 'uppercase',
letterSpacing: '0.15em',
},
children: tag,
},
},
// Main Title
{
type: 'div',
props: {
style: {
fontSize: '88px',
fontWeight: '800',
lineHeight: 1.1,
letterSpacing: '-0.04em',
maxWidth: '1000px',
display: 'flex',
flexDirection: 'column',
},
children: title,
},
},
],
},
},
{
width: 1200,
height: 630,
fonts: [
{
name: 'Atkinson',
data: boldFont,
weight: 700,
style: 'normal',
},
{
name: 'Atkinson',
data: semiBoldFont,
weight: 600,
style: 'normal',
},
],
}
);
const resvg = new Resvg(svg, {
fitTo: {
mode: 'width',
value: isThumb ? 800 : 1200,
},
});
const pngData = resvg.render();
const pngBuffer = pngData.asPng();
return new Response(new Uint8Array(pngBuffer), {
headers: {
'Content-Type': 'image/png',
'Cache-Control': 'public, max-age=31536000, immutable',
},
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment