1- // routes/og.ts - Dynamic OG image generator
1+ // routes/og.ts - Dynamic OG image generator with PNG output
22import { FreshContext } from "fresh" ;
3+ import { Resvg } from "npm:@resvg/resvg-js" ;
34
45export async function handler (
56 ctx : FreshContext ,
@@ -16,10 +17,21 @@ export async function handler(
1617 // Replace [[INSERT TITLE]] with the actual title (or empty string for homepage)
1718 svgContent = svgContent . replace ( "[[INSERT TITLE]]" , title ) ;
1819
19- // Return the SVG with proper headers
20- return new Response ( svgContent , {
20+ // Convert SVG to PNG using resvg
21+ const resvg = new Resvg ( svgContent , {
22+ fitTo : {
23+ mode : "width" ,
24+ value : 1200 , // Standard OG image width
25+ } ,
26+ } ) ;
27+
28+ const pngData = resvg . render ( ) ;
29+ const pngBuffer = pngData . asPng ( ) ;
30+
31+ // Return the PNG with proper headers
32+ return new Response ( pngBuffer , {
2133 headers : {
22- "Content-Type" : "image/svg+xml " ,
34+ "Content-Type" : "image/png " ,
2335 "Cache-Control" : "public, max-age=31536000, immutable" ,
2436 } ,
2537 } ) ;
@@ -30,12 +42,33 @@ export async function handler(
3042 try {
3143 const coverPath = `${ Deno . cwd ( ) } /static/images/cover.svg` ;
3244 const svgContent = await Deno . readTextFile ( coverPath ) ;
33- return new Response ( svgContent , {
34- headers : {
35- "Content-Type" : "image/svg+xml" ,
36- "Cache-Control" : "public, max-age=3600" ,
37- } ,
38- } ) ;
45+
46+ // Try to convert fallback to PNG as well
47+ try {
48+ const resvg = new Resvg ( svgContent , {
49+ fitTo : {
50+ mode : "width" ,
51+ value : 1200 ,
52+ } ,
53+ } ) ;
54+ const pngData = resvg . render ( ) ;
55+ const pngBuffer = pngData . asPng ( ) ;
56+
57+ return new Response ( pngBuffer , {
58+ headers : {
59+ "Content-Type" : "image/png" ,
60+ "Cache-Control" : "public, max-age=3600" ,
61+ } ,
62+ } ) ;
63+ } catch {
64+ // If PNG conversion fails, return SVG as last resort
65+ return new Response ( svgContent , {
66+ headers : {
67+ "Content-Type" : "image/svg+xml" ,
68+ "Cache-Control" : "public, max-age=3600" ,
69+ } ,
70+ } ) ;
71+ }
3972 } catch {
4073 return new Response ( "Image not found" , { status : 404 } ) ;
4174 }
0 commit comments