| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364 |
- import { pageMetadata } from "@/lib/page-metadata"
- export const metadata = pageMetadata("docs/api/image")
- # @json-render/image
- Image renderer. Turn JSON specs into SVG and PNG images using [Satori](https://github.com/vercel/satori).
- ## Install
- ```bash
- npm install @json-render/core @json-render/image
- ```
- For PNG output, also install the optional peer dependency:
- ```bash
- npm install @resvg/resvg-js
- ```
- See the [Image example](https://github.com/vercel-labs/json-render/tree/main/examples/image) for a full working example.
- ## schema
- The image element schema for image specs. Use with `defineCatalog` from core.
- ```typescript
- 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`.
- ```typescript
- 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
- ```typescript
- interface RenderOptions {
- registry?: ComponentRegistry;
- includeStandard?: boolean; // default: true
- state?: Record<string, unknown>;
- fonts?: SatoriOptions['fonts'];
- width?: number;
- height?: number;
- }
- ```
- <table>
- <thead>
- <tr>
- <th>Option</th>
- <th>Type</th>
- <th>Default</th>
- <th>Description</th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td><code>fonts</code></td>
- <td><code>{"SatoriOptions['fonts']"}</code></td>
- <td><code>[]</code></td>
- <td>Font data for text rendering (required for meaningful output)</td>
- </tr>
- <tr>
- <td><code>width</code></td>
- <td><code>number</code></td>
- <td>Frame prop</td>
- <td>Override the output image width</td>
- </tr>
- <tr>
- <td><code>height</code></td>
- <td><code>number</code></td>
- <td>Frame prop</td>
- <td>Override the output image height</td>
- </tr>
- <tr>
- <td><code>registry</code></td>
- <td><code>{"Record<string, ComponentRenderer>"}</code></td>
- <td><code>{"{}"}</code></td>
- <td>Custom component map (merged with standard components)</td>
- </tr>
- <tr>
- <td><code>includeStandard</code></td>
- <td><code>boolean</code></td>
- <td><code>true</code></td>
- <td>Include built-in standard components</td>
- </tr>
- <tr>
- <td><code>state</code></td>
- <td><code>{"Record<string, unknown>"}</code></td>
- <td><code>{"{}"}</code></td>
- <td>Initial state for <code>$state</code> / <code>$cond</code> dynamic prop resolution</td>
- </tr>
- </tbody>
- </table>
- ## Standard Components
- ### Root
- #### Frame
- Root image container. Defines the output image dimensions and background. Must be the root element.
- ```typescript
- {
- 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.
- ```typescript
- {
- 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.
- ```typescript
- {
- 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.
- ```typescript
- {
- 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.
- ```typescript
- {
- 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.
- ```typescript
- {
- 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.
- ```typescript
- {
- src: string;
- width: number | null;
- height: number | null;
- borderRadius: number | null;
- objectFit: "contain" | "cover" | "fill" | "none" | null;
- }
- ```
- ### Decorative
- #### Divider
- Horizontal line separator.
- ```typescript
- {
- color: string | null;
- thickness: number | null;
- marginTop: number | null;
- marginBottom: number | null;
- }
- ```
- #### Spacer
- Empty vertical space.
- ```typescript
- {
- height: number | null;
- }
- ```
- ## Catalog Definitions
- Pre-built definitions for creating image catalogs:
- ```typescript
- 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:
- ```typescript
- import { schema, standardComponentDefinitions } from '@json-render/image/server';
- ```
- ## Sub-path Exports
- <table>
- <thead>
- <tr>
- <th>Export</th>
- <th>Description</th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td><code>@json-render/image</code></td>
- <td>Full package: schema, renderer, components, render functions</td>
- </tr>
- <tr>
- <td><code>@json-render/image/server</code></td>
- <td>Schema and catalog definitions only (no React or Satori)</td>
- </tr>
- <tr>
- <td><code>@json-render/image/catalog</code></td>
- <td>Standard component definitions and types</td>
- </tr>
- <tr>
- <td><code>@json-render/image/render</code></td>
- <td>Server-side render functions only</td>
- </tr>
- </tbody>
- </table>
- ## Types
- <table>
- <thead>
- <tr>
- <th>Export</th>
- <th>Description</th>
- </tr>
- </thead>
- <tbody>
- <tr>
- <td><code>ImageSchema</code></td>
- <td>Schema type for image specs</td>
- </tr>
- <tr>
- <td><code>ImageSpec</code></td>
- <td>Spec type for image output</td>
- </tr>
- <tr>
- <td><code>RenderOptions</code></td>
- <td>Options for render functions</td>
- </tr>
- <tr>
- <td><code>ComponentRenderProps</code></td>
- <td>Props passed to component render functions</td>
- </tr>
- <tr>
- <td><code>ComponentRenderer</code></td>
- <td>Component render function type</td>
- </tr>
- <tr>
- <td><code>ComponentRegistry</code></td>
- <td>Map of component names to render functions</td>
- </tr>
- <tr>
- <td><code>StandardComponentDefinitions</code></td>
- <td>Type of the standard component definitions object</td>
- </tr>
- <tr>
- <td><code>StandardComponentProps{'<K>'}</code></td>
- <td>Inferred props type for a standard component by name</td>
- </tr>
- </tbody>
- </table>
|