A tiny, focused utility to make Satori accept dimension values when generating OG images from HTML or rendered Svelte components. It normalizes width/height attributes and inline styles to the numeric types Satori expects.
<img>
, <svg>
, and <image>
nodes produced by satori-html
auto
and percentagestoReactNode(...)
and satori(...)
pnpm add @humanspeak/svelte-satori-fix satori satori-html @resvg/resvg-js
# or
npm i -S @humanspeak/svelte-satori-fix satori satori-html @resvg/resvg-js
This mirrors the common Satori flow documented in the reference article.
// +server.ts (simplified)
import satori from 'satori'
import { Resvg } from '@resvg/resvg-js'
import { html as toReactNode } from 'satori-html'
const height = 630
const width = 1200
export const GET = async () => {
const node = toReactNode('<div style="color:red">Hello</div>')
const svg = await satori(node, { height, width })
const image = new Resvg(svg, { fitTo: { mode: 'width', value: width } }).render()
return new Response(image.asPng(), { headers: { 'content-type': 'image/png' } })
}
When rendering a Svelte component (e.g., OG.svelte
) to HTML, if it contains an <img>
with width
/height
as strings (e.g., "78" or "78px"), Satori can throw validation errors. Example render step:
// Somewhere in your route/handler
const result = render(OG, {}) // result.body is HTML; you may also capture component CSS
Use normalizeDimensionsForSatori
right after toReactNode(...)
and before satori(...)
.
import satori from 'satori'
import { Resvg } from '@resvg/resvg-js'
import { html as toReactNode } from 'satori-html'
import { normalizeDimensionsForSatori } from '@humanspeak/svelte-satori-fix'
// result from your component render
const result = render(OG, {})
const css = '' // if you collected CSS for the component, include it here
// Build a single HTML string, then convert to a Satori node
const element = normalizeDimensionsForSatori(toReactNode(`${result.body}<style>${css}</style>`))
// Proceed with Satori and PNG output
const svg = await satori(element, { height: 630, width: 1200 })
const image = new Resvg(svg, { fitTo: { mode: 'width', value: 1200 } }).render()
return new Response(image.asPng(), { headers: { 'content-type': 'image/png' } })
width
/height
attributes and inline style.width
/style.height
to numbers (e.g., 78
) where safe, which Satori expects for <img>
, <svg>
, and <image>
.auto
and percentages (e.g., 50%
) are preserved.import { normalizeDimensionsForSatori } from '@humanspeak/svelte-satori-fix'
normalizeDimensionsForSatori(node)
Node | Node[] | null
(tree produced by satori-html
)img
, svg
, image
: coerces props.width
/props.height
when safestyle
: coerces style.width
/style.height
when safechildren
arrays/objectsIf importing within this repo:
import { normalizeDimensionsForSatori } from '$lib/utils/main'
toReactNode(...)
and satori(...)
MIT © Humanspeak, Inc.
Made with ❤️ by Humanspeak