This guide walks you through integrating the CreativeEditor SDK (CE.SDK) Engine—without its built-in UI—into a SvelteKit application. This setup is ideal for building a fully custom editing interface or automating creative workflows purely through code, with no human interaction required.
Who Is This Guide For?
This guide is for developers who:
- Want to design a custom UI instead of using CE.SDK’s default editor.
- Intend to integrate CE.SDK into automation workflows or server components without rendering a visual editor.
- Have completed a “Getting Started with CE.SDK in SvelteKit” tutorial and are ready to explore more advanced use cases.
What You’ll Achieve
- Initialize CE.SDK’s headless engine in a client-side SvelteKit component.
- Programmatically create and modify a CE.SDK scene.
- Add a custom button that reduces the opacity of an image by 20% on each click.
- (Optional) Render the CE.SDK canvas while still controlling the editor with your own UI.
Prerequisites
Before starting, ensure you have:
- A working SvelteKit project.
- Followed the “Getting Started with CE.SDK in SvelteKit” tutorial.
- A valid CE.SDK license key (start a free trial to get one).
Step 1: Install CE.SDK Engine
To use CE.SDK in headless mode in SvelteKit, install the library via the @cesdk/engine
npm package:
npm install @cesdk/engine
Step 2: Create a Custom Editor Component With Headless UI
Inside your src/lib/
folder, create a file named CustomEditor.svelte
and add this code:
<script> import { onMount } from 'svelte'; import CreativeEngine from '@cesdk/engine';
// to store the DOM container where the CreativeEngine canvas will be attached let canvasContainer; // to store the CreativeEngine instance let engine; // to store the ID of the image block added to the scene let imageBlockId = null;
onMount(async () => { // your CE.SDK configurations const config = { license: '<YOUR_CE_SDK_LICENSE>', // replace this with your CE.SDK license };
// initialize CreativeEngine in headless mode engine = await CreativeEngine.init(config);
// append CE.SDK canvas to the DOM (optional) if (canvasContainer && engine.element) { canvasContainer.appendChild(engine.element); }
// get the current scene or create a new one let scene = engine.scene.get(); if (!scene) { scene = engine.scene.create(); const page = engine.block.create('page'); engine.block.appendChild(scene, page); }
// get the first page block const [page] = engine.block.findByType('page');
// append a block to show an image on the page const imageBlock = engine.block.create('graphic'); imageBlockId = imageBlock; engine.block.setShape(imageBlock, engine.block.createShape('rect'));
// fill the block with an image from a public source const imageFill = engine.block.createFill('image'); engine.block.setSourceSet(imageFill, 'fill/image/sourceSet', [ { uri: 'https://img.ly/static/ubq_samples/sample_1_1024x683.jpg', width: 1024, height: 683, }, ]); engine.block.setFill(imageBlock, imageFill); engine.block.appendChild(page, imageBlock);
// zoom to fit the page in the editor view engine.scene.zoomToBlock(page); });
// callback to change the opacity of the image function changeOpacity() { if (engine && imageBlockId != null) { // get the current opacity value of the image const currentOpacity = engine.block.getOpacity(imageBlockId); // reduce the opacity of the image by 20% at each click engine.block.setOpacity(imageBlockId, currentOpacity * 0.8); } }</script>
<div class="editor-container"> <div class="canvas-container" bind:this="{canvasContainer}"></div> <div class="button-overlay"> <button on:click="{changeOpacity}">Reduce Opacity</button> </div></div>
Once you’ve initialized CreativeEngine, you can access the scene, which lets you programmatically create elements and update their properties. In this example, we add a sample image to the scene and create a button that decreases the image’s opacity by 20% every time it’s clicked.
In detail, the changeOpacity()
function utilizes the headless CE.SDK block
API to retrieve the image’s current opacity and adjust it dynamically.
Note: Attaching the CE.SDK canvas to the DOM is optional. You can use the engine entirely for automated processing in the browser—no UI required. For example, you could reduce the opacity of an image in memory and export it without ever rendering it on screen.
Consider styling your custom component with:
<style> .editor-container { width: 100vw; height: 100vh; position: relative; }
.canvas-container { width: 100%; height: 100%; }
.button-overlay { position: absolute; top: 20px; left: 20px; }
.button-overlay button { border-radius: 8px; border: 1px solid #ccc; padding: 0.6em 1.2em; font-size: 1em; font-weight: 500; font-family: inherit; background-color: #ffffff; color: #1a1a1a; cursor: pointer; transition: border-color 0.25s, box-shadow 0.25s; box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1); }
.button-overlay button:hover { border-color: #646cff; box-shadow: 0 4px 10px rgba(100, 108, 255, 0.2); }
.button-overlay button:focus, .button-overlay button:focus-visible { outline: 2px solid #646cff; outline-offset: 2px; }</style>
Optional: If you’re using src/lib/index.js
to centralize exports, add this line to it:
export { default as CustomEditor } from './CustomEditor.svelte';
Step 3: Use the Creative Editor Component
Because CreativeEngine operates in the browser, it must be rendered client-side. To do so, in the <script>
section of an SSR component or route, dynamically import and render the editor only when the app is running in the browser with:
import { browser } from "$app/environment"; // true only if the app is running in the browser// use the browser flag to conditionally render client-side componentslet isClient = browser;
let CustomEditor;if (isClient) { // dynamically import the CustomEditor component only in the browser import("$lib/CustomEditor.svelte").then(module => { CustomEditor = module.default; });}
**Note**: `[browser](https://svelte.dev/docs/kit/$app-environment#browser)` from `$app/environment` is `true` only when the app is running in the browser—not during server-side rendering.
Alternatively, if you exported `CustomEditor` from `src/lib/index.js`, you can simplify the dynamic import like this:
import("$lib").then(module => { CustomEditor = module.CustomEditor;});
Next, ensure that the editor component is only rendered on the client side. In the template section of your SvelteKit route or component, wrap it like this:
{#if isClient && CreativeEditorSDK} <CreativeEditorSDK />{/if}
Now, when you start your SvelteKit app and navigate to the page containing <CustomEditor>
, you’ll see a sample image on the canvas along with a “Reduce Opacity” button. Clicking the button will reduce the image’s opacity by 20% each time.
Use Cases
Congratulations! You’ve laid the groundwork for:
- Building fully customized creative tools with SvelteKit.
- Automating the generation of graphics and visual content.
- Controlling the CE.SDK engine programmatically in browser-based workflows.
- Developing server-side image or video manipulation features using
@cesdk/node
as explained in our “Getting Started with CE.SDK in Node.js” guide.
Troubleshooting & Common Errors
❌ Error: Error when evaluating SSR module /src/routes/+page.svelte: document is not defined
- Ensure that the
CustomEditor
component is dynamically imported in/src/routes/+page.svelte
and only rendered on the client side.
❌ Error: CE.SDK canvas doesn’t render
- Make sure you’re appending
engine.element
to a valid HTML node. - Double-check that the DOM reference exists and is properly attached when the engine is initialized.
❌ Error: Internal server error: Failed to resolve import "@cesdk/engine" from "src/lib/CustomEditor.svelte". Does the file exist?
- Confirm that you’ve installed CreativeEngine using the command
npm install @cesdk/engine
.
❌ Error: Missing license key in config
- Ensure your
config
object includes alicense
property and that it’s set to your CE.SDK license key.
❌ Error: Editor engine could not be loaded: The License Key (API Key) you are using to access CE.SDK is invalid
- Verify that your license key is correct, hasn’t expired, and is properly added to the configuration.
❌ Issue: The component doesn’t behave as expected
- Double-check your component paths and import statements.
- Open the browser console and inspect any runtime errors that might help identify the issue.
Next Steps
This guide has set the stage for: