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-htmlauto 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