Skip to content

Commit 2f3568f

Browse files
committed
feat: convert svg to png
1 parent 6873832 commit 2f3568f

File tree

3 files changed

+122
-52
lines changed

3 files changed

+122
-52
lines changed

deno.lock

Lines changed: 78 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

routes/og.ts

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
// routes/og.ts - Dynamic OG image generator
1+
// routes/og.ts - Dynamic OG image generator with PNG output
22
import { FreshContext } from "fresh";
3+
import { Resvg } from "npm:@resvg/resvg-js";
34

45
export 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
}

static/images/cover.svg

Lines changed: 1 addition & 42 deletions
Loading

0 commit comments

Comments
 (0)