Skip to content

New Nuxt.js Project Without UI

This guide explains how to use the CreativeEditor SDK (CE.SDK) Engine in headless mode within a Nuxt.js application. This setup is perfect for creating a fully custom editing experience or for automating design workflows entirely through code—without relying on the built-in visual editor.

Who Is This Guide For?

This guide is intended for developers who:

  • Want to create a custom user interface instead of using the default CE.SDK editor.
  • Need to integrate CE.SDK into client-side automation workflows without displaying a visual editor.
  • Have already completed the “Getting Started with CE.SDK in Nuxt.js” tutorial and are ready to dive into more advanced use cases.

What You’ll Achieve

  • Initialize the CE.SDK headless engine within a client-side Nuxt.js component.
  • Programmatically create and modify a scene—including a custom button that reduces the opacity of a sample image by 20% each time it’s clicked.
  • (Optional) Render the CE.SDK canvas for visual feedback while maintaining full control via your custom UI.

Prerequisites

Before you begin, make sure you have the following:

  • A working Nuxt.js 3 project.
  • The “Getting Started with CE.SDK in Nuxt.js” tutorial completed.
  • A valid CE.SDK license key (start a free trial to get yours).

Step 1: Install CE.SDK Engine

To use CE.SDK in headless mode within your Nuxt.js project, install the SDK via the @cesdk/engine npm package:

Terminal window
npm install @cesdk/engine

Step 2: Define a Custom Component for Your Headless CE.SDK Integration

Inside the /components folder of your Nuxt.js project (or wherever you store your components), create a new file named CustomEditor.vue defining the following component:

<template>
<div style="width: 100vw; height: 100vh; position: relative">
<div ref="canvasRef" style="width: 100%; height: 100%"></div>
<div class="button-overlay">
<div style="position: absolute; top: 20px; left: 20px">
<button @click="changeOpacity">Reduce Opacity</button>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import CreativeEngine from '@cesdk/engine';
// DOM reference to hold the CE.SDK canvas
const canvasRef = ref(null);
// to keep track of the ID of the added image block
let imageBlockId = null;
// to keep track of the CreativeEngine instance
let engine = null;
onMounted(async () => {
// CE.SDK configuration
const config = {
license: '<YOUR_CE_SDK_LICENSE>', // replace with your actual license key
};
// initialize CreativeEngine in headless mode
engine = await CreativeEngine.init(config);
// attach CE.SDK canvas to the DOM (optional)
if (canvasRef.value) {
canvasRef.value.appendChild(engine.element);
}
// get or create a new scene
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');
// create a graphic block and set its shape
imageBlockId = engine.block.create('graphic');
engine.block.setShape(imageBlockId, engine.block.createShape('rect'));
// fill the graphic block with a public image
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(imageBlockId, imageFill);
engine.block.appendChild(page, imageBlockId);
// zoom to fit the page in the canvas
engine.scene.zoomToBlock(page);
});
// reduce the image opacity by 20% each click
function changeOpacity() {
if (engine && imageBlockId != null) {
// get the current opacity value on the image
const currentOpacity = engine.block.getOpacity(imageBlockId);
// reduce the image opacity by 20%
engine.block.setOpacity(imageBlockId, currentOpacity * 0.8);
}
}
</script>

Once the CreativeEngine is initialized, you gain full programmatic control over your scene. In this example, a sample image is added to the canvas, and a button is included that reduces its opacity by 20% each time it’s clicked.

In detail, the changeOpacity() function demonstrates how to interact with CE.SDK’s headless block API. With that, you retrieve the current opacity of the image block and update it dynamically in the code.

Note: Attaching the CE.SDK canvas to the DOM is completely optional. You can use the engine entirely in headless mode—modifying scenes and assets directly in memory without rendering a visual interface. For instance, you could adjust image properties like opacity or dimensions in the browser, trigger a file download, and never display a UI at all.

From here, you’re ready to tailor the editor’s behavior and appearance to fit your exact needs. For example, you can style your custom editor with:

<style scoped>
.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 0.6em;
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);
width: 150px;
}
.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>

Step 3: Create a Client-Side Editor Component

The CreativeEngine relies on browser-specific features like document—and it performs dynamic DOM manipulation when attaching to the canvas. Because of that, the CustomEditor component must run only on the client side. In other words, it should never be server-side rendered (SSR).

To enforce client-only rendering, you can wrap CustomEditor with Nuxt’s <ClientOnly> component. To avoid repeating this logic wherever you want to render the editor, create a wrapper component called CustomEditorNoSSR.vue in your components/ directory:

<template>
<ClientOnly>
<CustomEditor />
</ClientOnly>
</template>

This wrapper ensures that the CustomEditor component is rendered exclusively on the client.

Note: As an alternative, you can simply rename CustomEditor.vue to CustomEditor.client.vue. Nuxt automatically recognizes the .client.vue suffix and guarantees that the component is rendered only on the client—making it ideal for auto-import scenarios without extra boilerplate.

Step 4: Use the Creative Editor Component

You can use your non-SSR editor component like this:

<CustomEditorNoSSR />

Or, if you renamed the file to CustomEditor.client.vue:

<CustomEditor />

Once your Nuxt.js app is running, navigate to the page where the editor is rendered. You’ll see a sample image on the canvas and a “Reduce Opacity” button. Each time you click the button, the image’s opacity is reduced by 20%.

Use Cases

Congratulations! You’ve just laid the groundwork for more advanced use cases, such as:

  • Building fully customized UIs using Nuxt.js components alongside the CE.SDK canvas.
  • Automating the creation of graphics or marketing materials directly in the browser.
  • Integrating CE.SDK into rich, multi-step creative browser workflows using programmatic logic.
  • Adding server-side image or video processing features with @cesdk/node—as shown in our “Getting Started with CE.SDK in Node.js” guide.

Troubleshooting & Common Errors

❌ Error: document is not defined

  • This error occurs when the CE.SDK Engine attempts to access the document object on the server side. To resolve that, check that the CustomEditor component is rendered as a client-only component. Wrap it with <ClientOnly>y or rename it as .client.vue.

❌ Error: CE.SDK canvas doesn’t render

  • Ensure that you’re appending engine.element to a valid DOM element. Double-check that the Vue.js ref is correct and that the element is properly attached to the DOM.

❌ Error: Failed to resolve import "@cesdk/engine" from "components/CustomEditor.vue". Does the file exist?

  • Make sure that you’ve successfully installed the CE.SDK Engine by running the command npm install @cesdk/engine.

❌ Error: Editor engine could not be loaded: The License Key (API Key) you are using to access CE.SDK is invalid

  • Confirm that your license key is valid, hasn’t expired, and is correctly configured in config.

❌ The component doesn’t behave as expected

  • Verify that your component paths and imports are accurate.
  • Review the browser console for any specific errors.

Next Steps

This guide sets the groundwork for: