Create social media images locally in your browser. Share the link. Nothing is
uploaded.
This ES module uses static WebAssembly instance imports and includes SVG, PNG,
and WebP output. Remove imports and output calls that your application does not use.
import * as ogImageRenderer from "./text-to-og-image-svg-inter.wasm";
import * as svgRasterizer from "./svg-rasterize-to-bmp-b8g8r8a8-srgb.wasm";
import * as pngEncoder from "./bmp-to-png.wasm";
import * as webpEncoder from "./bmp-b8g8r8a8-srgb-to-webp-lossless.wasm";
const encoder = new TextEncoder();
const decoder = new TextDecoder("utf-8", { fatal: true });
export function renderOGImageToSVG({
title = "",
subtitle = "",
textColor = 0xffffffff,
backgroundColor = 0x4b2e83ff,
fontMaxSize = 112,
fontWeight = 700,
} = {}) {
const form = new URLSearchParams({ title, subtitle }).toString();
const input = new Uint8Array(
ogImageRenderer.memory.buffer,
ogImageRenderer.input_ptr(),
ogImageRenderer.input_utf8_cap(),
);
const { read, written } = encoder.encodeInto(form, input);
if (read !== form.length) {
throw new RangeError("Open Graph image input is too large");
}
ogImageRenderer.uniform_set_text_color(textColor);
ogImageRenderer.uniform_set_background_color(backgroundColor);
ogImageRenderer.uniform_set_font_max_size(fontMaxSize);
ogImageRenderer.uniform_set_font_weight(fontWeight);
const outputSize = ogImageRenderer.render(written);
if (outputSize > ogImageRenderer.output_utf8_cap()) {
throw new RangeError("Open Graph image output is too large");
}
return decoder.decode(new Uint8Array(
ogImageRenderer.memory.buffer,
ogImageRenderer.output_ptr(),
outputSize,
));
}
export function renderOGImageToPNG(options) {
const svg = renderOGImageToSVG(options);
const input = new Uint8Array(
svgRasterizer.memory.buffer,
svgRasterizer.input_ptr(),
svgRasterizer.input_utf8_cap(),
);
const { read, written } = encoder.encodeInto(svg, input);
if (read !== svg.length) {
throw new RangeError("Open Graph SVG is too large to rasterize");
}
const bmpSize = svgRasterizer.render(written);
if (bmpSize > svgRasterizer.output_bytes_cap()) {
throw new RangeError("Open Graph BMP output is too large");
}
const bmp = new Uint8Array(
svgRasterizer.memory.buffer,
svgRasterizer.output_ptr(),
bmpSize,
);
if (bmp.length > pngEncoder.input_bytes_cap()) {
throw new RangeError("Open Graph BMP input is too large");
}
new Uint8Array(
pngEncoder.memory.buffer,
pngEncoder.input_ptr(),
bmp.length,
).set(bmp);
const pngSize = pngEncoder.render(bmp.length);
if (pngSize > pngEncoder.output_bytes_cap()) {
throw new RangeError("Open Graph PNG output is too large");
}
return new Uint8Array(
pngEncoder.memory.buffer,
pngEncoder.output_ptr(),
pngSize,
).slice();
}
export function renderOGImageToWebp(options) {
const svg = renderOGImageToSVG(options);
const input = new Uint8Array(
svgRasterizer.memory.buffer,
svgRasterizer.input_ptr(),
svgRasterizer.input_utf8_cap(),
);
const { read, written } = encoder.encodeInto(svg, input);
if (read !== svg.length) {
throw new RangeError("Open Graph SVG is too large to rasterize");
}
const bmpSize = svgRasterizer.render(written);
if (bmpSize > svgRasterizer.output_bytes_cap()) {
throw new RangeError("Open Graph BMP output is too large");
}
const bmp = new Uint8Array(
svgRasterizer.memory.buffer,
svgRasterizer.output_ptr(),
bmpSize,
);
if (bmp.length > webpEncoder.input_bytes_cap()) {
throw new RangeError("Open Graph BMP input is too large");
}
new Uint8Array(
webpEncoder.memory.buffer,
webpEncoder.input_ptr(),
bmp.length,
).set(bmp);
const webpSize = webpEncoder.render(bmp.length);
if (webpSize > webpEncoder.output_bytes_cap()) {
throw new RangeError("Open Graph WebP output is too large");
}
return new Uint8Array(
webpEncoder.memory.buffer,
webpEncoder.output_ptr(),
webpSize,
).slice();
}
const options = {
title: "Reusable components",
subtitle: "Rendered locally with embedded Inter paths",
textColor: 0xffffffff,
backgroundColor: 0x4b2e83ff,
fontMaxSize: 112,
fontWeight: 700,
};
const svg = renderOGImageToSVG(options);
const png = renderOGImageToPNG(options);
const webp = renderOGImageToWebp(options);
console.log({ svg, png, webp });