github-actions[bot] 6225fc41eb chore: version packages (#211) 4 ヶ月 前
..
src 553c803422 image (#173) 4 ヶ月 前
CHANGELOG.md 6225fc41eb chore: version packages (#211) 4 ヶ月 前
README.md 553c803422 image (#173) 4 ヶ月 前
package.json 6225fc41eb chore: version packages (#211) 4 ヶ月 前
tsconfig.json 553c803422 image (#173) 4 ヶ月 前
tsup.config.ts 553c803422 image (#173) 4 ヶ月 前

README.md

@json-render/image

Image renderer for @json-render/core. Generate SVG and PNG images from JSON specs using Satori.

Install

npm install @json-render/core @json-render/image

For PNG output, also install the optional peer dependency:

npm install @resvg/resvg-js

Quick Start

Render a spec to SVG

import { renderToSvg } from "@json-render/image/render";
import type { Spec } from "@json-render/core";

const spec: Spec = {
  root: "frame",
  elements: {
    frame: {
      type: "Frame",
      props: { width: 1200, height: 630, backgroundColor: "#1a1a2e" },
      children: ["heading", "subtitle"],
    },
    heading: {
      type: "Heading",
      props: { text: "Hello World", level: "h1", color: "#ffffff" },
      children: [],
    },
    subtitle: {
      type: "Text",
      props: { text: "Generated from JSON", fontSize: 24, color: "#a0a0b0" },
      children: [],
    },
  },
};

const svg = await renderToSvg(spec, {
  fonts: [
    {
      name: "Inter",
      data: await fetch("https://example.com/Inter-Regular.ttf").then((r) =>
        r.arrayBuffer()
      ),
      weight: 400,
      style: "normal",
    },
  ],
});

Render to PNG

import { renderToPng } from "@json-render/image/render";

const png = await renderToPng(spec, {
  fonts: [
    {
      name: "Inter",
      data: await readFile("./Inter-Regular.ttf"),
      weight: 400,
      style: "normal",
    },
  ],
});

// Write to file
await writeFile("output.png", png);

With a custom catalog

import { defineCatalog } from "@json-render/core";
import { schema, renderToSvg } from "@json-render/image";
import { standardComponentDefinitions } from "@json-render/image/catalog";
import { z } from "zod";

const catalog = defineCatalog(schema, {
  components: {
    ...standardComponentDefinitions,
    Badge: {
      props: z.object({
        label: z.string(),
        color: z.string().nullable(),
      }),
      slots: [],
      description: "A colored badge label",
    },
  },
});

Standard Components

Root

Component Description
Frame Root image container. Defines width, height, and background. Must be the root element.

Layout

Component Description
Box Generic container with padding, margin, background, border, and flex alignment.
Row Horizontal flex layout with gap, align, justify.
Column Vertical flex layout with gap, align, justify.

Content

Component Description
Heading h1-h4 heading text with color and alignment.
Text Body text with fontSize, color, weight, style, and alignment.
Image Image from a URL with width, height, and borderRadius.

Decorative

Component Description
Divider Horizontal line separator.
Spacer Empty vertical space.

Server-Side APIs

import { renderToSvg, renderToPng } from "@json-render/image/render";

// Render to an SVG string
const svg = await renderToSvg(spec, { fonts });

// Render to a PNG buffer (requires @resvg/resvg-js)
const png = await renderToPng(spec, { fonts });

Options

Option Type Default Description
fonts SatoriOptions['fonts'] [] Font data for text rendering
width number Frame prop Override image width
height number Frame prop Override image height
registry Record<string, Component> {} Custom component overrides
includeStandard boolean true Include standard components
state Record<string, unknown> {} Initial state values

Server-Safe Import

Import schema and catalog definitions without pulling in React or Satori:

import { schema, standardComponentDefinitions } from "@json-render/image/server";

License

Apache-2.0