Skip to content

Commit 1cd57c0

Browse files
author
Miriad
committed
debug: bypass HTMLRewriter — pass React element directly to ImageResponse
Level 1 HTML that worked before now fails on current deploy. This suggests HTMLRewriter/parseHtml is the root cause. Testing with React element object to skip HTML parsing entirely.
1 parent cfe3a24 commit 1cd57c0

File tree

1 file changed

+28
-31
lines changed

1 file changed

+28
-31
lines changed

apps/web/src/pages/api/og/default.png.ts

Lines changed: 28 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,54 @@
11
/**
2-
* Default OG image — systematic isolation test.
3-
* Tests increasingly complex HTML to find the breaking point.
2+
* Default OG image — bypass HTMLRewriter by using React elements directly.
3+
* workers-og's og() accepts React.ReactNode, skipping parseHtml entirely.
44
*/
55
import type { APIRoute } from "astro";
66
import { ImageResponse } from "workers-og";
7-
import { generateDefaultOgHtml, loadFonts } from "../../../lib/og-utils";
7+
import { loadFonts } from "../../../lib/og-utils";
88

99
export const prerender = false;
1010

1111
export const GET: APIRoute = async ({ url }) => {
12-
const level = url.searchParams.get("level") || "full";
13-
14-
// Level 1: Single div (known working)
15-
const html1 = '<div style="display:flex;width:1200px;height:630px;background:#000;color:#fff;font-size:48px;align-items:center;justify-content:center">Hello World</div>';
16-
17-
// Level 2: Two nested divs
18-
const html2 = '<div style="display:flex;width:1200px;height:630px;background:#000"><div style="display:flex;color:#fff;font-size:48px;align-items:center;justify-content:center;width:100%;height:100%">Hello World</div></div>';
19-
20-
// Level 3: Column layout with 3 children
21-
const html3 = '<div style="display:flex;width:1200px;height:630px;background:#000;padding:60px"><div style="display:flex;flex-direction:column;width:100%;height:100%;justify-content:space-between"><div style="display:flex;color:#fff;font-size:24px">Top</div><div style="display:flex;color:#fff;font-size:48px">Middle</div><div style="display:flex;color:#fff;font-size:16px">Bottom</div></div></div>';
22-
23-
// Level 4: Logo with emoji + spans
24-
const html4 = '<div style="display:flex;width:1200px;height:630px;background:#000;padding:60px"><div style="display:flex;flex-direction:column;width:100%;height:100%;justify-content:space-between"><div style="display:flex;align-items:center;gap:12px"><div style="font-size:40px">🐱</div><div style="display:flex;font-size:24px;font-weight:700;color:#fff"><span>CodingCat</span><span style="color:#7c3aed">.dev</span></div></div><div style="display:flex;color:#fff;font-size:48px">Title</div><div style="display:flex;color:#888;font-size:16px">codingcat.dev</div></div></div>';
25-
26-
// Level 5: Full template
27-
const html5 = generateDefaultOgHtml({ title: "Test Title" });
28-
29-
const htmlMap: Record<string, string> = { "1": html1, "2": html2, "3": html3, "4": html4, "5": html5, full: html5 };
30-
const html = htmlMap[level] || html5;
31-
32-
if (url.searchParams.get("mode") === "dump") {
33-
return new Response(html, { headers: { "Content-Type": "text/plain" } });
34-
}
35-
3612
try {
37-
const response = new ImageResponse(html, {
13+
// Pass a React element directly — bypasses HTMLRewriter parseHtml
14+
const element = {
15+
type: "div",
16+
props: {
17+
style: {
18+
display: "flex",
19+
width: 1200,
20+
height: 630,
21+
background: "#000",
22+
color: "#fff",
23+
fontSize: 48,
24+
alignItems: "center",
25+
justifyContent: "center",
26+
},
27+
children: "Hello World",
28+
},
29+
};
30+
31+
const response = new ImageResponse(element as any, {
3832
width: 1200,
3933
height: 630,
4034
fonts: loadFonts(),
4135
});
4236

4337
const buffer = await response.arrayBuffer();
4438
if (buffer.byteLength === 0) {
45-
return new Response(JSON.stringify({ error: "Empty buffer", level }), {
39+
return new Response(JSON.stringify({ error: "Empty buffer" }), {
4640
status: 500, headers: { "Content-Type": "application/json" },
4741
});
4842
}
4943

5044
return new Response(buffer, {
51-
headers: { "Content-Type": "image/png", "Content-Length": buffer.byteLength.toString() },
45+
headers: {
46+
"Content-Type": "image/png",
47+
"Content-Length": buffer.byteLength.toString(),
48+
},
5249
});
5350
} catch (e: any) {
54-
return new Response(JSON.stringify({ error: e.message, level }), {
51+
return new Response(JSON.stringify({ error: e.message, stack: e.stack }), {
5552
status: 500, headers: { "Content-Type": "application/json" },
5653
});
5754
}

0 commit comments

Comments
 (0)