@json-render/image
Image renderer. Turn JSON specs into SVG and PNG images using Satori.
Install
npm install @json-render/core @json-render/imageFor PNG output, also install the optional peer dependency:
npm install @resvg/resvg-jsSee the Image example for a full working example.
schema
The image element schema for image specs. Use with defineCatalog from core.
import { defineCatalog } from '@json-render/core';
import { schema, standardComponentDefinitions } from '@json-render/image';
const catalog = defineCatalog(schema, {
components: standardComponentDefinitions,
});Render Functions
Server-side functions for producing image output. Both accept a spec and optional RenderOptions.
import { renderToSvg, renderToPng } from '@json-render/image/render';
const svg = await renderToSvg(spec, { fonts });
const png = await renderToPng(spec, { fonts });
await writeFile('output.png', png);RenderOptions
interface RenderOptions {
registry?: ComponentRegistry;
includeStandard?: boolean; // default: true
state?: Record<string, unknown>;
fonts?: SatoriOptions['fonts'];
width?: number;
height?: number;
}| Option | Type | Default | Description |
|---|---|---|---|
fonts | SatoriOptions['fonts'] | [] | Font data for text rendering (required for meaningful output) |
width | number | Frame prop | Override the output image width |
height | number | Frame prop | Override the output image height |
registry | Record<string, ComponentRenderer> | {} | Custom component map (merged with standard components) |
includeStandard | boolean | true | Include built-in standard components |
state | Record<string, unknown> | {} | Initial state for $state / $cond dynamic prop resolution |
Standard Components
Root
Frame
Root image container. Defines the output image dimensions and background. Must be the root element.
{
width: number;
height: number;
backgroundColor: string | null;
padding: number | null;
display: "flex" | "none" | null;
flexDirection: "row" | "column" | null;
alignItems: "flex-start" | "center" | "flex-end" | "stretch" | null;
justifyContent: "flex-start" | "center" | "flex-end" | "space-between" | "space-around" | null;
}Layout
Box
Generic container with padding, margin, background, border, and flex alignment. Supports absolute positioning.
{
padding: number | null;
paddingTop: number | null;
paddingBottom: number | null;
paddingLeft: number | null;
paddingRight: number | null;
margin: number | null;
backgroundColor: string | null;
borderWidth: number | null;
borderColor: string | null;
borderRadius: number | null;
flex: number | null;
width: number | string | null;
height: number | string | null;
alignItems: "flex-start" | "center" | "flex-end" | "stretch" | null;
justifyContent: "flex-start" | "center" | "flex-end" | "space-between" | "space-around" | null;
flexDirection: "row" | "column" | null;
position: "relative" | "absolute" | null;
top: number | null;
left: number | null;
right: number | null;
bottom: number | null;
overflow: "visible" | "hidden" | null;
}Row
Horizontal flex layout with optional wrapping.
{
gap: number | null;
alignItems: "flex-start" | "center" | "flex-end" | "stretch" | null;
justifyContent: "flex-start" | "center" | "flex-end" | "space-between" | "space-around" | null;
padding: number | null;
flex: number | null;
wrap: boolean | null;
}Column
Vertical flex layout.
{
gap: number | null;
alignItems: "flex-start" | "center" | "flex-end" | "stretch" | null;
justifyContent: "flex-start" | "center" | "flex-end" | "space-between" | "space-around" | null;
padding: number | null;
flex: number | null;
}Content
Heading
Heading text at various levels. h1 is largest, h4 is smallest.
{
text: string;
level: "h1" | "h2" | "h3" | "h4" | null;
color: string | null;
align: "left" | "center" | "right" | null;
letterSpacing: number | string | null;
lineHeight: number | null;
}Text
Body text with configurable size, color, weight, and alignment.
{
text: string;
fontSize: number | null;
color: string | null;
align: "left" | "center" | "right" | null;
fontWeight: "normal" | "bold" | null;
fontStyle: "normal" | "italic" | null;
lineHeight: number | null;
letterSpacing: number | string | null;
textDecoration: "none" | "underline" | "line-through" | null;
}Image
Image from a URL with optional dimensions and fit.
{
src: string;
width: number | null;
height: number | null;
borderRadius: number | null;
objectFit: "contain" | "cover" | "fill" | "none" | null;
}Decorative
Divider
Horizontal line separator.
{
color: string | null;
thickness: number | null;
marginTop: number | null;
marginBottom: number | null;
}Spacer
Empty vertical space.
{
height: number | null;
}Catalog Definitions
Pre-built definitions for creating image catalogs:
import { standardComponentDefinitions } from '@json-render/image/catalog';
import { defineCatalog } from '@json-render/core';
import { schema } from '@json-render/image';
const catalog = defineCatalog(schema, {
components: {
...standardComponentDefinitions,
// Add custom components
},
});Server-Safe Import
Import schema and catalog definitions without pulling in React or Satori:
import { schema, standardComponentDefinitions } from '@json-render/image/server';Sub-path Exports
| Export | Description |
|---|---|
@json-render/image | Full package: schema, renderer, components, render functions |
@json-render/image/server | Schema and catalog definitions only (no React or Satori) |
@json-render/image/catalog | Standard component definitions and types |
@json-render/image/render | Server-side render functions only |
Types
| Export | Description |
|---|---|
ImageSchema | Schema type for image specs |
ImageSpec | Spec type for image output |
RenderOptions | Options for render functions |
ComponentRenderProps | Props passed to component render functions |
ComponentRenderer | Component render function type |
ComponentRegistry | Map of component names to render functions |
StandardComponentDefinitions | Type of the standard component definitions object |
StandardComponentProps<K> | Inferred props type for a standard component by name |