diff --git a/Dockerfile b/Dockerfile index a6bf930..b2ab0ad 100644 --- a/Dockerfile +++ b/Dockerfile @@ -77,8 +77,9 @@ RUN apk add --no-cache ca-certificates tzdata # Copy Rust binary COPY --from=final-builder /build/target/release/api ./api -# Copy Bun SSR server +# Copy Bun SSR server and client assets (including fonts for OG images) COPY --from=frontend /build/build/server ./web/build/server +COPY --from=frontend /build/build/client ./web/build/client COPY --from=frontend /build/build/*.js ./web/build/ COPY web/console-logger.js ./web/ diff --git a/web/src/lib/og-fonts.ts b/web/src/lib/og-fonts.ts index f6f5481..2837f1a 100644 --- a/web/src/lib/og-fonts.ts +++ b/web/src/lib/og-fonts.ts @@ -1,42 +1,24 @@ -import { readFile } from "node:fs/promises"; -import { join } from "node:path"; -import { cwd } from "node:process"; +import { read } from "$app/server"; import type { SatoriOptions } from "satori"; +// Import fonts as URLs - Vite will copy them to build output +import hankenGroteskUrl from "@fontsource/hanken-grotesk/files/hanken-grotesk-latin-900-normal.woff?url"; +import schibstedGroteskUrl from "@fontsource/schibsted-grotesk/files/schibsted-grotesk-latin-400-normal.woff?url"; +import interUrl from "@fontsource/inter/files/inter-latin-500-normal.woff?url"; + /** * 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). + * Uses SvelteKit's read() to access fonts from build output. + * Works in all deployment environments (Docker, edge, serverless). * * Note: Only WOFF/TTF/OTF formats are supported by Satori (not WOFF2). */ export async function loadOGFonts(): Promise { - // 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"); - + // Use SvelteKit's read() - works in all deployment environments 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", - ), - ), + read(hankenGroteskUrl).arrayBuffer(), + read(schibstedGroteskUrl).arrayBuffer(), + read(interUrl).arrayBuffer(), ]); return [