Search Docs
Loading...
Skip to content

Headless

CreativeEditor SDK (CE.SDK) Headless Mode with native Node.js bindings lets your backend render scenes and exports with native C++ performance.

The @cesdk/node-native package provides CE.SDK’s full feature set through native C++ bindings, delivering better performance than the WASM-based @cesdk/node package.

You orchestrate the same actions a user can do from the UI using the CreativeEngine, which powers all CE.SDK features.

Common Use Cases#

  • Automated pipelines: Generate batches of personalized assets from templates.
  • Server-rendered previews: Produce thumbnails or proofs before a user ever opens the editor.
  • Custom tooling: Embed CE.SDK logic inside CLI tools, workers, or queue processors.
  • Compliance and governance: Enforce template rules during backend render jobs without exposing editing controls.

When to Use Headless Mode#

ScenarioHeadless (Node.js Native)UI-Based Editor
Cron or queue-driven exportsYesNo
Rendering without a browserYesNo
Letting users tweak the layoutNoYes
Mixing custom UI with CE.SDK toolsYesHybrid

How Headless Mode Works with Native Bindings#

@cesdk/node-native provides the same Engine API as @cesdk/node. Without needing a DOM, your script can run server-side to:

  • Start the engine.
  • Edit and export assets.

You are responsible for:

  • Handling file Input/Output.
  • Monitoring memory.
  • Disposing of the engine when the job ends.

Available Features#

  • Create/edit scenes, pages, and blocks programmatically.
  • Export compositions (complete edited scenes) in your desired format.

Requirements#

  • Node.js v20+ (or the matching runtime for your serverless provider).
  • @cesdk/node-native installed locally: npm install @cesdk/node-native.
  • A valid CE.SDK license key.
  • A supported platform: macOS (ARM or x64) or Linux (x64).

Quick Start: Initialize the Engine#

To try out the CE.SDK headless mode with native bindings:

  1. Open/create a Node.js project.
  2. Install the native Node.js package:
Terminal window
npm install @cesdk/node-native

1. Create a CE.SDK Helper#

Create a reusable script that initializes the engine:

CesdkHelper.js
import CreativeEngine from '@cesdk/node-native';
// CE.SDK config
const defaultConfig = {
license: process.env.LICENSE_KEY ?? '<YOUR_CESDK_LICENSE_KEY>',
};
let engine;
// Export the CE.SDK initialization to reuse it.
export async function getCreativeEngine(config = defaultConfig) {
if (!engine) {
engine = await CreativeEngine.init(config);
}
return engine;
}
export function disposeCreativeEngine() {
if (!engine) {
return;
}
engine.dispose();
engine = undefined;
}
export function getCreativeEngineConfig() {
return defaultConfig;
}

This pattern is ideal for:

  • HTTP handlers
  • Queue workers

Each invocation:

  1. Calls getCreativeEngine().
  2. Reuses the same instance.
  3. Disposes of the engine when your process shuts down to release native resources.

2. Reuse the Engine in a Script#

You can now script actions using CE.SDK. In the following example, the script assembles a greeting card entirely on the server.

In your Node.js project:

  1. Create a new script.
  2. Import your helper along with the needed feature:
GreetingCard.js
import { writeFile } from 'node:fs/promises';
import { disposeCreativeEngine, getCreativeEngine } from './CesdkHelper.js';
  1. Copy-paste the following function:
GreetingCard.js
async function buildGreeting() {
// Get the engine
const engine = await getCreativeEngine();
try {
// Create a scene and append it to the page
const scene = engine.scene.create();
const page = engine.block.create('page');
engine.block.setWidth(page, 800);
engine.block.setHeight(page, 600);
engine.block.appendChild(scene, page);
// Create an image block from a sample URL
const imageBlock = engine.block.create('graphic');
engine.block.setShape(imageBlock, engine.block.createShape('rect'));
const imageFill = engine.block.createFill('image');
engine.block.setString(
imageFill,
'fill/image/imageFileURI',
'https://img.ly/static/ubq_samples/sample_1.jpg',
);
engine.block.setFill(imageBlock, imageFill);
engine.block.setPosition(imageBlock, 100, 100);
engine.block.setWidth(imageBlock, 300);
engine.block.setHeight(imageBlock, 300);
engine.block.appendChild(page, imageBlock);
// Create a text block
const textBlock = engine.block.create('text');
engine.block.setString(textBlock, 'text/text', 'Hello from Headless Mode!');
engine.block.setPosition(textBlock, 100, 450);
engine.block.setWidth(textBlock, 600);
engine.block.appendChild(page, textBlock);
// Export the page as PNG
const pngBuffer = await engine.block.export(page, 'image/png');
// Write the file on disk
await writeFile('greeting-card.png', Buffer.from(pngBuffer));
console.log('Export complete: greeting-card.png');
} catch (error) {
console.error('Failed to export headless scene', error);
} finally {
// Dispose the Engine to free resources
disposeCreativeEngine();
}
}
buildGreeting().catch(error => {
console.error('Unexpected failure', error);
process.exitCode = 1;
});
  1. Run the script node ./<path-to-your-file>/GreetingCard.js.
  2. Check that your project contains the greeting-card.png file.

The preceding script:

  • Calls the CesdkHelper.js helper to start the engine.
  • Builds a scene containing:
    • An image
    • A text block.
  • Exports the page to a PNG Uint8Array.
  • Writes the image to the disk.
  • Disposes of the engine.

Go Further#