11/**
2- * Default OG image generation for generic pages.
3- *
4- * Uses workers-og (Satori + resvg-wasm) to generate 1200x630 PNG images
5- * on Cloudflare Workers. Simpler layout — just branding + title + optional subtitle.
6- * Used for homepage, author pages, and other generic pages.
7- *
8- * Usage: /api/og/default.png?title=About+Us&subtitle=Learn+more+about+CodingCat.dev
9- *
10- * Query params:
11- * - title (required): Page title
12- * - subtitle (optional): Subtitle text
2+ * Default OG image — debug version to surface runtime errors.
133 */
144import type { APIRoute } from "astro" ;
155import { ImageResponse } from "workers-og" ;
@@ -21,21 +11,55 @@ export const GET: APIRoute = async ({ url }) => {
2111 try {
2212 const title = url . searchParams . get ( "title" ) || "CodingCat.dev" ;
2313 const subtitle = url . searchParams . get ( "subtitle" ) || undefined ;
24-
2514 const html = generateDefaultOgHtml ( { title, subtitle } ) ;
15+ const fonts = loadFonts ( ) ;
16+
17+ // Debug: font info
18+ const fontDebug = fonts . map ( ( f : any ) => ( {
19+ name : f . name ,
20+ weight : f . weight ,
21+ dataType : typeof f . data ,
22+ isUint8Array : f . data instanceof Uint8Array ,
23+ isArrayBuffer : f . data instanceof ArrayBuffer ,
24+ length : f . data ?. byteLength || f . data ?. length || 0 ,
25+ constructor : f . data ?. constructor ?. name ,
26+ first4Bytes : f . data ? Array . from ( new Uint8Array ( f . data instanceof ArrayBuffer ? f . data : f . data . buffer || f . data ) . slice ( 0 , 4 ) ) : null ,
27+ } ) ) ;
2628
27- const response = new ImageResponse ( html , {
29+ // Await the body to catch stream errors
30+ const ogResponse = new ImageResponse ( html , {
2831 width : 1200 ,
2932 height : 630 ,
30- fonts : loadFonts ( ) ,
33+ fonts,
3134 } ) ;
3235
33- response . headers . set ( "Cache-Control" , OG_CACHE_HEADER ) ;
36+ const body = await ogResponse . arrayBuffer ( ) ;
3437
35- return response ;
38+ if ( body . byteLength === 0 ) {
39+ return new Response (
40+ JSON . stringify ( {
41+ error : "Empty body from ImageResponse" ,
42+ fontDebug,
43+ htmlSnippet : html . slice ( 0 , 500 ) ,
44+ } ) ,
45+ { status : 500 , headers : { "Content-Type" : "application/json" } }
46+ ) ;
47+ }
48+
49+ return new Response ( body , {
50+ status : 200 ,
51+ headers : {
52+ "Content-Type" : "image/png" ,
53+ "Content-Length" : body . byteLength . toString ( ) ,
54+ } ,
55+ } ) ;
3656 } catch ( error : any ) {
3757 return new Response (
38- JSON . stringify ( { error : error . message , stack : error . stack } ) ,
58+ JSON . stringify ( {
59+ error : error . message ,
60+ stack : error . stack ,
61+ name : error . name ,
62+ } ) ,
3963 { status : 500 , headers : { "Content-Type" : "application/json" } }
4064 ) ;
4165 }
0 commit comments