Skip to content
Apexify.jsDocs
Apexify.js version v5.4.5

Advanced / Scene · guide

renderScene

Current Apexify.js 6.0.0 documentation for renderScene.

apexify.jsRuntime: nodeCURRENTSince 6.0.0

renderScene(input: SceneRenderInput, options?: SceneRenderOptions): Promise<Buffer> validates and renders a scene to PNG bytes.

Validation is mandatory. The deprecated validate option may still appear in older TypeScript code for source compatibility, but it is ignored and cannot disable safety checks. Use maxSurfaceDepth only to impose a stricter nesting cap than the configured runtime limit.


Plain object

SOURCEtypescript
typescript
Studio
import { ApexPainter } from "apexify.js";import fs from "node:fs"; const painter = new ApexPainter(); const png = await painter.renderScene({  width: 1200,  height: 630,  background: { colorBg: "#1d4ed8" },  layers: [    {      type: "text",      texts: [        { text: "Social card", x: 60, y: 200, fontSize: 64, color: "#ffffff" },        { text: "apexify.js", x: 60, y: 300, fontSize: 28, color: "#bfdbfe" },      ],    },  ],}); await fs.promises.writeFile("card.png", png);

Explicit preflight for untrusted input

Use the painter method when you want to reject a payload before entering a larger workflow. Rendering performs the same validation again at its boundary.

SOURCEtypescript
typescript
Studio
import { ApexPainter } from "apexify.js";import type { SceneRenderInput } from "apexify.js"; const painter = new ApexPainter(); function parseScene(json: unknown): SceneRenderInput {  const input = json as SceneRenderInput;  painter.validateSceneRenderInput(input, { maxSurfaceDepth: 16 });  return input;}

There is no public trusted-input bypass.


Named assets ($name, $palette.key)

renderScene resolves string asset references through painter.assets by default. Pass { resolveAssetRefs: false } only when the scene is already resolved or $ must remain literal data.

SOURCEtypescript
typescript
Studio
painter.assets.loadPalette("brand", { bg: "#020617", text: "#f8fafc" }); await painter.renderScene({  width: 640,  height: 360,  background: { colorBg: "$brand.bg" },  layers: [    { type: "text", texts: { text: "Resolved", x: 40, y: 80, fontSize: 36, color: "$brand.text" } },  ],});

See Named assets for $$ escaping, dotted paths, Buffers, values, and explicit replacement.


SceneBuilder.render

SOURCEtypescript
typescript
Studio
const png = await painter  .createScene(960, 540)  .setBackground({ colorBg: "#020617" })  .addLayers([    {      type: "path",      path: [        { type: "moveTo", x: 48, y: 120 },        { type: "lineTo", x: 400, y: 120 },      ],      options: { stroke: { color: "#38bdf8", width: 4 } },    },    {      type: "text",      texts: { text: "Builder", x: 48, y: 160, fontSize: 48, color: "#f1f5f9" },    },  ])  .render({ maxSurfaceDepth: 16 });

Builder asset resolution is off by default. Use .render({ resolveAssetRefs: true }) for builders created by painter.createScene() when the snapshot contains $ references.


Reuse one scene for PNG, GIF, and video

SOURCEtypescript
typescript
Studio
import type { SceneRenderInput } from "apexify.js"; const baseScene = {  width: 1080,  height: 1080,  background: { colorBg: "#111827" },  layers: [],} satisfies SceneRenderInput; const png = await painter.renderScene(baseScene);// await painter.renderSceneToGIF(baseScene, { options: { ... }, sceneRender: { maxSurfaceDepth: 16 } });// await painter.renderSceneToVideoFrames(baseScene, { options: { ... }, sceneRender: { maxSurfaceDepth: 16 } });

Scene→video performs cheap structural frame validation before spending work on the composed scene raster.


Dynamic scenes

SOURCEtypescript
typescript
Studio
function buildScene(theme: "light" | "dark") {  const bg = theme === "dark" ? "#0f172a" : "#f8fafc";  const fg = theme === "dark" ? "#e2e8f0" : "#0f172a";  return {    width: 400,    height: 200,    background: { colorBg: bg },    layers: [      { type: "text" as const, texts: { text: theme, x: 24, y: 80, fontSize: 32, color: fg } },    ],  };} const darkPng = await painter.renderScene(buildScene("dark"));const lightPng = await painter.renderScene(buildScene("light"));

Error handling

Scene validation/resource failures retain their structured Apexify error types such as ApexifyInputError and ApexifyResourceLimitError. Unexpected rendering/decode failures become ApexifyDecodeError with the original cause preserved.

Validation covers scene budgets and known domain inputs, but application-level policy still belongs to your application—for example, whether a particular local file path should be permitted.


Next steps