---
title: "How To Build a Canva Clone with CE.SDK"
description: "Build a Canva-style design editor in React with CE.SDK: templates, locked layers, custom assets, and export, in a few hundred lines."
url: "https://img.ly/blog/how-to-build-a-canva-clone-with-ce-sdk/"
type: "blog"
date: "2022-07-27"
author: "Antonello"
tags: ["React","How-To","Design Editor","Tutorial","Learning"]
---

> This is the markdown version of [How To Build a Canva Clone with CE.SDK](https://img.ly/blog/how-to-build-a-canva-clone-with-ce-sdk/). For all pages in one file, see [llms-full.txt](https://img.ly/llms-full.txt). For an index of all available pages, see [llms.txt](https://img.ly/llms.txt).

---

Canva taught a very large number of people what a design tool should feel like. If your product has any design surface, whether that is book covers, t-shirt artwork, or social posts, that is the bar users measure you against.

The good news is that the hard part is not the editor. It is templates: giving people a starting point, then controlling exactly what they can change so the output stays on brand. This guide builds that in React with CreativeEditor SDK (CE.SDK).

If you would rather read working code than a tutorial, the finished project is on GitHub at [imgly/canva-clone-react-cesdk](https://github.com/imgly/canva-clone-react-cesdk), and there is a [prebuilt Canva clone solution](https://img.ly/docs/cesdk/react/prebuilt-solutions/canva-clone-19de75.md) in the docs you can drop in as a starting point.

## What CE.SDK gives you

[CreativeEditor SDK](https://img.ly/products/creative-sdk.md) is an [embeddable design editor](https://img.ly/capabilities/embeddable-editor.md) that runs inside your own app, on your own domain. You mount it as a component, point it at your assets, and it handles the canvas, the layer model, text, images, and export.

The part that makes a Canva clone rather than a drawing tool is its role model. CE.SDK separates the person who builds a template from the person who fills it in.

### Creator mode

In [Creator mode](https://img.ly/docs/cesdk/react/configuration-2c1c3d.md), you build the template. Add and arrange elements, apply filters and background removal, and then decide what the next person is allowed to touch.

Two features carry most of the weight. [Placeholders](https://img.ly/docs/cesdk/react/create-templates/add-dynamic-content/placeholders-d9ba8a.md) mark an element as replaceable and control whether it can be deleted, restyled, or duplicated. [Text variables](https://img.ly/docs/cesdk/react/create-templates/add-dynamic-content/text-variables-7ecb50.md) let you define a token like `{{Name}}` and set it from code, which is how you batch-generate a hundred personalized cards from one design.

![creator-mode-cesdk](https://blog.img.ly/2022/07/creator-mode-cesdk.gif)

### Adopter mode

Adopter mode is what your end users get. They can change colors, text, and images, but only where the template's creator allowed it. Everything else is locked, so a customer cannot accidentally drag the logo off the canvas or delete the legal line.

![adopter-mode](https://blog.img.ly/2022/07/adopter-mode.gif)

That split is the whole trick. It is why a template-based editor produces usable output at scale and a blank canvas does not.

## Build it

### Prerequisites

- Node.js 20+ and npm 10+
- A React 18+ project on a modern build tool
- A CE.SDK license key. [Start a free trial](https://img.ly/docs/cesdk/) to get one.

Create a project with [Vite](https://vite.dev/guide/):

```bash
npm create vite@latest canva-clone -- --template react
cd canva-clone
npm install @cesdk/cesdk-js
```

### Step 1: Mount the editor

CE.SDK ships a React component, so you do not manage the instance lifecycle yourself. Import it from the `/react` entry point and pass a `config` object and an `init` function.

```jsx
// src/DesignEditor.jsx
import CreativeEditor from '@cesdk/cesdk-js/react';

const config = {
  license: 'YOUR_LICENSE_KEY',
  userId: 'YOUR_USER_ID',
};

const init = async (cesdk) => {
  await Promise.all([
    cesdk.addDefaultAssetSources(),
    cesdk.addDemoAssetSources({
      sceneMode: 'Design',
      withUploadAssetSources: true,
    }),
  ]);

  await cesdk.createDesignScene();
};

export default function DesignEditor() {
  return (
    <CreativeEditor config={config} init={init} width="100vw" height="100vh" />
  );
}
```

That already gives you a working design editor with stock assets, fonts, shapes, and upload. Render it from `App.jsx` and run `npm run dev`.

Name your own component something other than `CreativeEditor`, or it collides with the import.

### Step 2: Add a template library

Templates are the difference between a design tool and a Canva clone. You register a template source, add assets to it, and tell CE.SDK what to do when a user picks one.

```javascript
const init = async (cesdk) => {
  const engine = cesdk.engine;

  await cesdk.addDefaultAssetSources();
  await cesdk.createDesignScene();

  // Register a source and define what happens on click
  engine.asset.addLocalSource('my.templates', undefined, async (asset) => {
    const uri = asset.meta?.uri;
    const scene = engine.scene.get();
    if (!uri || scene == null) return undefined;

    await engine.scene.applyTemplateFromURL(
      new URL(uri, window.location.href).href
    );
    return scene;
  });

  // Add templates to it
  engine.asset.addAssetToSource('my.templates', {
    id: 'postcard-1',
    label: { en: 'Postcard' },
    tags: { en: ['postcard', 'card'] },
    groups: ['cards'],
    meta: {
      thumbUri:
        'https://cdn.img.ly/assets/demo/v3/ly.img.template/thumbnails/cesdk_postcard_1.jpg',
      uri: 'https://cdn.img.ly/packages/imgly/cesdk-js/latest/assets/templates/cesdk_postcard_1.scene',
    },
  });
};
```

`applyTemplateFromURL` is the important call. It applies the template to the current scene rather than replacing it wholesale, which preserves the user's session and any content they have already added.

In production, `addAssetToSource` is where your own designs go. A template is a `.scene` file, so the loop is: build it in Creator mode, save it, host it, and register it here with a thumbnail.

If you are generating designs from data rather than letting users pick, `engine.scene.loadFromURL()` plus `engine.variable.setString()` plus `engine.block.export()` is the batch path. The [template library docs](https://img.ly/docs/cesdk/react/use-templates/library-b3c704.md) cover both directions.

### Step 3: Export

```javascript
const page = engine.scene.getCurrentPage();
const blob = await engine.block.export(page, { mimeType: 'image/png' });

const anchor = document.createElement('a');
anchor.href = URL.createObjectURL(blob);
anchor.download = 'design.png';
anchor.click();
```

PNG covers most on-screen use. If people are ordering physical prints, export [print-ready PDF](https://img.ly/docs/cesdk/js/export-save-publish/for-printing-bca896.md) instead, which handles CMYK and bleed properly.

## A note on the old version of this guide

Earlier versions of this tutorial configured templates through a `presets.templates` object passed into `CreativeEditorSDK.init()`. Both were removed. `init()` became `create()`, which does not build a scene for you and instead lets you configure the SDK first, and `presets` gave way to the Asset API shown above. If you are maintaining an integration written against the old shape, the docs carry per-version [migration notes](https://img.ly/docs/cesdk/react/to-v1-77-e7f3a1.md) listing every changed option.

## Let an agent build it

If you work in an AI-assisted editor, [Agent Skills for CE.SDK](https://img.ly/docs/cesdk/react/get-started/agent-skills-f7g8h9.md) load the current documentation into Claude Code, Cursor, and similar tools, so you get code written against today's API rather than the version that happened to be in the training data. That matters here more than usual, because this exact tutorial was outdated for a while and models learned from it. There is also an [MCP server](https://img.ly/docs/cesdk/react/get-started/mcp-server-fde71c.md) for live lookup. Background in [Introducing IMG.LY Agent Skills](https://img.ly/blog/img-ly-agent-skills-web.md).

## Where to take it

The obvious next steps are your own templates and your own assets. After that:

- **Custom UI.** Reorder or replace editor components with `setComponentOrder({ in: location }, order)`, and register your own buttons and panels. See the [UI extensions guide](https://img.ly/docs/cesdk/react/user-interface/ui-extensions-d194d1.md).
- **Theming.** Match your product with `cesdk.ui.setTheme()` or the [theme generator](https://img.ly/docs/cesdk/react/user-interface/appearance/theming-4b0938.md).
- **Brand assets.** Serve fonts, logos, and imagery from your own backend so users only see approved material.
- **Automation.** Text variables plus the engine API generate personalized designs at volume. We built an [NFT art collection generator](https://img.ly/blog/how-to-generate-an-nft-art-collection-with-react-using-ce-sdk.md) on exactly that.

If you are coming from Canva's own API rather than starting fresh, two follow-ups go deeper: why teams move to a [white-label alternative to Canva Connect](https://img.ly/blog/img-ly-a-canva-connect-api-alternative-for-white-label-scalable-editing.md), and a step-by-step guide to [migrating from Canva Connect to the IMG.LY SDK](https://img.ly/blog/migrating-from-canva-connect-api-to-img-ly-sdk-a-practical-implementation-guide.md).

Questions about your use case? [Talk to us](https://img.ly/forms/contact-sales.md).

---

## More Resources

- **[IMG.LY Website](https://img.ly/index.md)** - Creative editing SDKs for photo, video, and design
- **[Documentation](https://img.ly/docs/cesdk/)** - CE.SDK developer documentation
- **[Contact Sales](https://img.ly/forms/contact-sales.md)** - Get a custom quote. A public JSON API accepts the request directly, no account or key needed. Ask your user for consent and their details first.
