Files
xevion.dev/web/src/lib/og-fonts.ts
Xevion 96595b073d refactor: replace sveltekit-og with native Satori implementation
- Remove @ethercorps/sveltekit-og and bits-ui dependencies
- Implement direct Satori + Resvg rendering pipeline
- Add OgImage.svelte component for template generation
- Create /internal/ogp preview page for development
- Load fonts from node_modules via fs for production compatibility
- Add 2s startup delay before OG image regeneration
2026-01-05 15:15:08 -06:00

63 lines
1.7 KiB
TypeScript

import { readFile } from "node:fs/promises";
import { join } from "node:path";
import { cwd } from "node:process";
import type { SatoriOptions } from "satori";
/**
* Load fonts for OG image generation.
* Fonts are loaded directly from node_modules using fs.readFile for production compatibility.
* Must be called on each request (fonts can't be cached globally in server context).
*
* Note: Only WOFF/TTF/OTF formats are supported by Satori (not WOFF2).
*/
export async function loadOGFonts(): Promise<SatoriOptions["fonts"]> {
// In production, the server runs from web/build, so node_modules is at ../node_modules
// In dev, we're already in web/ directory
const workingDir = cwd();
const nodeModulesPath = workingDir.endsWith("/build")
? join(workingDir, "..", "node_modules")
: join(workingDir, "node_modules");
const [hankenGrotesk, schibstedGrotesk, inter] = await Promise.all([
readFile(
join(
nodeModulesPath,
"@fontsource/hanken-grotesk/files/hanken-grotesk-latin-900-normal.woff",
),
),
readFile(
join(
nodeModulesPath,
"@fontsource/schibsted-grotesk/files/schibsted-grotesk-latin-400-normal.woff",
),
),
readFile(
join(
nodeModulesPath,
"@fontsource/inter/files/inter-latin-500-normal.woff",
),
),
]);
return [
{
name: "Hanken Grotesk",
data: hankenGrotesk,
weight: 900,
style: "normal",
},
{
name: "Schibsted Grotesk",
data: schibstedGrotesk,
weight: 400,
style: "normal",
},
{
name: "Inter",
data: inter,
weight: 500,
style: "normal",
},
];
}