Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 13s
Build & Deploy / 🧪 QA (push) Successful in 2m51s
Build & Deploy / 🏗️ Build (push) Successful in 5m32s
Build & Deploy / 🚀 Deploy (push) Successful in 16s
Build & Deploy / 🔔 Notify (push) Successful in 1s
Build & Deploy / 🧪 Post-Deploy Verification (push) Failing after 5m12s
This commit reapplies fixes directly to main after reverting an accidental feature branch merge. chore(release): bump version to 2.2.6
69 lines
2.2 KiB
TypeScript
69 lines
2.2 KiB
TypeScript
import { ImageResponse } from 'next/og';
|
|
import { getPostBySlug } from '@/lib/blog';
|
|
import { OGImageTemplate } from '@/components/OGImageTemplate';
|
|
import { getOgFonts, OG_IMAGE_SIZE } from '@/lib/og-helper';
|
|
import { SITE_URL } from '@/lib/schema';
|
|
|
|
export const size = OG_IMAGE_SIZE;
|
|
export const contentType = 'image/png';
|
|
export const runtime = 'nodejs';
|
|
|
|
async function fetchImageAsBase64(url: string) {
|
|
try {
|
|
const res = await fetch(url);
|
|
if (!res.ok) return undefined;
|
|
const arrayBuffer = await res.arrayBuffer();
|
|
const buffer = Buffer.from(arrayBuffer);
|
|
const contentType = res.headers.get('content-type') || 'image/jpeg';
|
|
return `data:${contentType};base64,${buffer.toString('base64')}`;
|
|
} catch (error) {
|
|
console.error('Failed to fetch OG image:', url, error);
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
export default async function Image({
|
|
params,
|
|
}: {
|
|
params: Promise<{ locale: string; slug: string }>;
|
|
}) {
|
|
const { locale, slug } = await params;
|
|
const post = await getPostBySlug(slug, locale);
|
|
|
|
if (!post) {
|
|
return new Response('Post not found', { status: 404 });
|
|
}
|
|
|
|
const fonts = await getOgFonts();
|
|
|
|
// We don't have request.url here, but we can assume the domain from SITE_URL or config
|
|
// For local images during dev, relative paths in <img> might not work in Satori
|
|
// but if we are in nodejs runtime, we could potentially read from disk.
|
|
// For now, let's just make sure it's absolute.
|
|
const featuredImage = post.frontmatter.featuredImage
|
|
? post.frontmatter.featuredImage.startsWith('http')
|
|
? post.frontmatter.featuredImage
|
|
: `${SITE_URL}${post.frontmatter.featuredImage}`
|
|
: undefined;
|
|
|
|
// Fetch image explicitly and convert to base64 because Satori sometimes struggles
|
|
// fetching remote URLs directly inside ImageResponse correctly in various environments.
|
|
let base64Image: string | undefined = undefined;
|
|
if (featuredImage) {
|
|
base64Image = await fetchImageAsBase64(featuredImage);
|
|
}
|
|
|
|
return new ImageResponse(
|
|
<OGImageTemplate
|
|
title={post.frontmatter.title}
|
|
description={post.frontmatter.excerpt}
|
|
label={post.frontmatter.category || 'Blog'}
|
|
image={base64Image || featuredImage}
|
|
/>,
|
|
{
|
|
...OG_IMAGE_SIZE,
|
|
fonts,
|
|
},
|
|
);
|
|
}
|