CreativeEditor SDK (CE.SDK) Headless Mode for Node.js lets your backend render scenes and exports without ever mounting the browser UI.
The @cesdk/node package bundles CE.SDK’s features so you can drive the Engine APIs from:
- Queues
- Cron jobs
- Serverless functions
- Etc.
You orchestrate the same actions a user can do from the UI using the CreativeEgine, 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#
| Scenario | Headless (Node.js) | UI-Based Editor |
|---|---|---|
| Cron or queue-driven exports | ✅ | ❌ |
| Rendering without a browser | ✅ | ❌ |
| Letting users tweak the layout | ❌ | ✅ |
| Mixing custom UI with CE.SDK tools | ✅ | Hybrid |
How Headless Mode Works on Node.js#
@cesdk/node imports the CreativeEngine runtime for Node.js, allowing you to execute the same Engine API calls. 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.
- Load templates and default asset libraries (
engine.addDefaultAssetSources()). - Export compositions (complete edited scenes) in your desired format.
Requirements to Run CreativeEngine on Node.js#
- Node.js 18+ (or the matching runtime for your serverless provider).
- @cesdk/node installed locally:
npm install @cesdk/node. - A valid CE.SDK license key.
- A base asset bundle reachable from the runtime (CDN or self-hosted path). The CDN URLs shown below work for quick tests.
Quick Start: Initialize the Engine#
To try out the CE.SDK headless mode:
- Open/create a Node.js project.
- Install the Node.js package:
npm install @cesdk/node1. Create a CE.SDK Helper#
Create a reusable script that does the following:
- Awaits the engine once.
- Loads the default assets
- Keeps the promise alive for further calls.
import CreativeEngine from '@cesdk/node';
// CE.SDK configconst defaultConfig = { license: process.env.LICENSE_KEY ?? '<YOUR_CESDK_LICENSE_KEY>'};
// Memorized initialization promise so initialization happens at most once at a time.let enginePromise;
// Export the CE.SDK initialization to reuse it.export async function getCreativeEngine(config = defaultConfig) { if (!enginePromise) { enginePromise = CreativeEngine.init(config).catch((error) => { enginePromise = undefined; throw error; }); }
return enginePromise;}
export async function disposeCreativeEngine() { if (!enginePromise) { return; }
const engine = await enginePromise; enginePromise = undefined; engine.dispose();}
export function getCreativeEngineConfig() { return defaultConfig;}This pattern is ideal for:
- HTTP handlers
- Queue workers
Each invocation:
- Awaits
getEngine(). - Reuses the same instance.
- 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:
- Create a new script.
- Import your helper along with the needed feature:
import { writeFile } from 'node:fs/promises';import { disposeCreativeEngine, getCreativeEngine } from './creativeEngineHelper.js';- Copy-paste the following function:
async function buildGreeting() { // Wait for the Engine to be ready before executing the function const engine = await getCreativeEngine();
try { await engine.addDefaultAssetSources();
// 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);
// Set the format on export const exportResult = await engine.block.export(page, { mimeType: 'image/png' }); const arrayBuffer = await exportResult.arrayBuffer();
// Write the file on disk await writeFile('greeting-card.png', Buffer.from(arrayBuffer)); console.log('Export complete: greeting-card.png'); } catch (error) { console.error('Failed to export headless scene', error); } finally { // Dispose the Engine to free resources await disposeCreativeEngine(); }}
buildGreeting().catch((error) => { console.error('Unexpected failure', error); process.exitCode = 1;});- Run the script
node ./<path-to-your-file>/GreetingCard.js. - Check that your project contains the
greeting-card.pngfile.
The preceding script:
- Calls the
CesdkHelper.jshelper to start the engine. - Builds a scene containing:
- An image
- A text block.
- Exports the page to a PNG
Blob - Writes the image to the disk.
- Disposes of the engine.
Go Further#
- Dig into the Node.js SDK reference for every available Engine call.
- Start a new Node.js headless project with a complete project template.
- Need to mix headless logic with UI-driven editing? Engine interface guides show hybrid patterns.