Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 11s
Build & Deploy / 🧪 QA (push) Successful in 1m31s
Build & Deploy / 🚀 Deploy (push) Has been cancelled
Build & Deploy / 🧪 Post-Deploy Verification (push) Has been cancelled
Build & Deploy / 🔔 Notify (push) Has been cancelled
Build & Deploy / 🏗️ Build (push) Has been cancelled
91 lines
2.6 KiB
TypeScript
91 lines
2.6 KiB
TypeScript
import { readFileSync } from 'fs';
|
|
import { join } from 'path';
|
|
|
|
/**
|
|
* Loads the Inter fonts for use in Satori (Next.js OG Image generation).
|
|
* Since we are using runtime = 'nodejs', we can read them from the filesystem.
|
|
*/
|
|
export async function getOgFonts() {
|
|
const boldFontPath = join(process.cwd(), 'public/fonts/Inter-Bold.woff');
|
|
const regularFontPath = join(process.cwd(), 'public/fonts/Inter-Regular.woff');
|
|
|
|
try {
|
|
console.log(`[OG] Loading fonts: bold=${boldFontPath}, regular=${regularFontPath}`);
|
|
const boldFontBuffer = readFileSync(boldFontPath);
|
|
const regularFontBuffer = readFileSync(regularFontPath);
|
|
|
|
// Satori (Vercel OG) strictly requires an ArrayBuffer, not a Node Buffer view.
|
|
const boldFont = boldFontBuffer.buffer.slice(
|
|
boldFontBuffer.byteOffset,
|
|
boldFontBuffer.byteOffset + boldFontBuffer.byteLength,
|
|
);
|
|
const regularFont = regularFontBuffer.buffer.slice(
|
|
regularFontBuffer.byteOffset,
|
|
regularFontBuffer.byteOffset + regularFontBuffer.byteLength,
|
|
);
|
|
|
|
console.log(
|
|
`[OG] Fonts loaded successfully (${boldFont.byteLength} and ${regularFont.byteLength} bytes)`,
|
|
);
|
|
|
|
return [
|
|
{
|
|
name: 'Inter',
|
|
data: boldFont,
|
|
weight: 700 as const,
|
|
style: 'normal' as const,
|
|
},
|
|
{
|
|
name: 'Inter',
|
|
data: regularFont,
|
|
weight: 400 as const,
|
|
style: 'normal' as const,
|
|
},
|
|
];
|
|
} catch (error) {
|
|
console.error(`[OG] Failed to load fonts from ${process.cwd()}:`, error);
|
|
return [];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Common configuration for OG images
|
|
*/
|
|
export const OG_IMAGE_SIZE = {
|
|
width: 1200,
|
|
height: 630,
|
|
};
|
|
|
|
/**
|
|
* Loads a local image and converts it to a base64 data URI for Satori
|
|
*/
|
|
export function getLocalImageBase64(filename: string): string | undefined {
|
|
try {
|
|
const filePath = join(process.cwd(), 'public', filename);
|
|
const buffer = readFileSync(filePath);
|
|
const ext = filename.split('.').pop()?.toLowerCase();
|
|
const mimeType =
|
|
ext === 'png'
|
|
? 'image/png'
|
|
: ext === 'jpg' || ext === 'jpeg'
|
|
? 'image/jpeg'
|
|
: 'image/svg+xml';
|
|
return `data:${mimeType};base64,${buffer.toString('base64')}`;
|
|
} catch (error) {
|
|
console.error(`[OG] Failed to load local image ${filename}:`, error);
|
|
return undefined;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns standard assets for OG images
|
|
*/
|
|
export function getOgAssets() {
|
|
return {
|
|
logo: getLocalImageBase64('logo-white.png'),
|
|
bgImage: getLocalImageBase64(
|
|
'media/aerial-view-of-electricity-station-surrounded-with-2023-11-27-05-33-40-utc-scaled.jpg',
|
|
),
|
|
};
|
|
}
|