Embed SDK Full Editor tutorial

Learn how to integrate the Adobe Express Embed SDK into your web applications.

<!-- TODO: add a video, Davide-style. -->

Introduction

Hi, developers! In this tutorial, we'll create an Embed SDK integration that leverages the Adobe Express full editor experience. Users will be able to create, edit, and export documents directly from your web application.

We'll look at a few configuration parameters, as well as the way to handle events, callbacks and manage files between your application and Adobe Express. Let's get started!

Full Editor

Prerequisites

Before we begin, make sure you have the following:

Running the sample project

Let's have a look at what we're going to build. First off, clone the embed-sdk-full-editor-tutorial sample from GitHub and navigate to the project directory. Locate the src/.env file and replace the placeholder string in the VITE_API_KEY with your Embed SDK API Key:

VITE_API_KEY="your-api-key-here!"

<!-- Inline Alert -->

data-variant=info
data-slots=text1
📖 Instructions on how to obtain an API Key can be found on the Quickstart Guide. Make sure your API Key is set to allow the localhost:5555 domain and port.

Now, you can install the dependencies and run the sample with the following two simple commands:

npm install
npm run start

The web application will be served at localhost:5555 on a secure HTTPS connection; HTTPS is always required for any Embed SDK integration. Open your browser and navigate to this address to see it in action.

Full Editor starting point

When clicking the Create New button, the Adobe Express full editor will launch with a predefined document size; users have the entire set of tools available to create their designs. Once they're done, they can Download the document, or Save it as an Image.

The sample project will handle the file transfer between Adobe Express and the web page hosting it, and the image will be displayed in lieu of the placeholder.

Full Editor displayed image

The Edit button (previously disabled) will open the Editor with the same document size and content as the one just created: the Project ID has been stored as part of the onPublish callback, as we'll see in due course. Users can modify the design and download or save it again.

<!-- Inline Alert -->

data-variant=error
data-slots=header, text1

Error: "Adobe Express is not available"

In case you get a popup when trying to launch the Adobe Express integration with the following message: "You do not have access to this service. Contact your IT administrator to gain access", please check to have entered the correct API Key in the src/.env file as described here.

Coding the Integration

You can just read the existing code in the sample, but it's always best to learn by doing! We suggest following along and typing the code in—even small mistakes can lead to important discoveries.

The sample project is a simple web application built with Vite, which takes care of the entire HTTPS setup and hot reloading.1 As customary, we'll work in the src folder with the simplest setup possible: HTML, JS, and CSS, one file each.

1. Importing and Initializing

The HTML content is not overly important; let's focus on the JavaScript side of things first. Open the project in your code editor of choice. In main.js, remove everything below the Spectrum import statements—we'll rebuild it from scratch.

import "./style.css";

// Importing theme and typography styles from Spectrum Web Components
import "@spectrum-web-components/styles/typography.css";
import "@spectrum-web-components/theme/express/theme-light.js";
import "@spectrum-web-components/theme/express/scale-medium.js";
import "@spectrum-web-components/theme/sp-theme.js";

// Importing Spectrum Web Components
import "@spectrum-web-components/button/sp-button.js";
import "@spectrum-web-components/button-group/sp-button-group.js";
import "@spectrum-web-components/divider/sp-divider.js";

The imports above allow us to style our web application with Spectrum Web Components and the Adobe Express theme. Let's begin by importing the Embed SDK:

// Importing the Adobe Express Embed SDK
await import("https://cc-embed.adobe.com/sdk/v4/CCEverywhere.js");
console.log("CCEverywhere loaded", window.CCEverywhere);

<!-- Inline Alert -->

data-variant=info
data-slots=text1
There are several ways to import CCEverywhere.js: for more information, please refer to the Quickstart Guide.

When the Embed SDK is imported, a CCEverywhere object is globally available and must be initialized. There are two sets of parameters that you can pass as option objects:

// 👀 Required parameters for initializing the Embed SDK
const hostInfo = {
  clientId: import.meta.env.VITE_API_KEY,
  // The appName must match the Public App Name in the Developer Console
  appName: "Embed SDK Sample",
};

// Optional parameters
const configParams = {
  // Users can log in only when exporting/saving the document
  loginMode: "delayed",
};

// Initializing the Adobe Express Embed SDK
const { editor } = await window.CCEverywhere.initialize(
  hostInfo,
  configParams
);

We're using the asynchronous initialize() method, that returns a promise resolving to an object with three properties. Here, we want to implement the full editor; hence, among them, we destructure just the editor.

The hostInfo object is required: the clientId contains your API Key (here, retrieved by Vite from the .env file) and the appName.

<!-- Inline Alert -->

data-variant=warning
data-slots=text1
The appName must match the Public App Name in the Developer Console, and it will be displayed in the Adobe Express UI as a folder where users can store their documents.

All configParams are optional, instead: here, loginMode tells Adobe Express to delay the login until artworks are exported.

2. Creating the Editor

Excellent! We have this editor: now what? We'll use it to spawn a new Adobe Express instance via the editor.create() method—which, in turn, accepts four option objects able to configure:

The links above point to the respective SDK Reference pages. They are all optional—our sample makes use of the first three of them:

// Document
const docConfig = { canvasSize: "BusinessCard" };
// Application
const appConfig = {
  selectedCategory: "media",
  callbacks: {
    onCancel: () => {},
    onPublish: (intent, publishParams) => { /* ... */ },
    onError: (err) => { /* ... */ }
};
// Export Options
const exportConfig = [
  {
    id: "download",
    label: "Download",
    action: { target: "download" },
    style: { uiType: "button" },
  },
  {
    id: "save-modified-asset",
    label: "Save image",
    action: { target: "publish" },
    style: { uiType: "button" },
  },
];

As you can see, we are:

On the Create New button click, Adobe Express is launched:

document.getElementById("createDesign").onclick = async () => {
  editor.create(docConfig, appConfig, exportConfig);
};

Launching the Full Editor

<!-- Info Alert -->

data-variant=info
data-slots=text1
Please don't be scared by the red warning toast at the bottom of the screen: it is just a reminder that the Embed SDK is providing access via your credentials, but you must submit the integration and request approval from Adobe before you can go live. Please check the Submission and Review section to learn more.

As you can see, integrating the full editor doesn't take much time! You can customize it to a great extent; even using all the default options, the result is brilliant.

3. Managing images

The exportConfig array we've just written adds a Save image button to Adobe Express, allowing users to store their image; we'd like our web application to capture and display it on the HTML page.

We need to write a simple function in the callbacks to implement this feature, precisely the onPublish. It is triggered when the user clicks the Save image button, and it receives a PublishParams argument, with three crucial properties:

The data property sounds promising! The plan is to have an <img> element (in this example, it starts as a placeholder), which src attribute will be filled with the Base64 string coming from Adobe Express.

data-slots=heading, code
data-repeat=2

main.js

// Storing the image element
var expressImage = document.getElementById("savedImage");

// Callbacks to be used when creating or editing a document
const callbacks = {
  // ... other callbacks
  onPublish: (intent, publishParams) => {                   // 👈
    expressImage.src = publishParams.asset[0].data;         // 👈
    console.log("Image data", publishParams.asset[0].data); // 👈
  }
};

index.html

<!-- ... rest of the page -->
<img id="savedImage"
     src="https://placehold.co/300x300?text=Placeholder+Image&font=source-sans-pro"
     alt="Your design will appear here." />
<!-- ... rest of the page -->

Please note that asset is an array; we're getting just the first item here. If you open the Console, you'll see the Base64 string logged.

Logging Base64 data

4. Editing projects

The last step is implementing the Edit button feature, which should launch Adobe Express and open the project that was saved before. As we've seen earlier, when a document is saved, we receive a PublishParams that contains documentId. We can store it for reference and use in the docConfig option object to open it again:

// Will hold the project ID when a document is saved
var existingProjectId = null; // 👈

// Callbacks to be used when creating or editing a document
const callbacks = {
  // ... other callbacks
  onPublish: (intent, publishParams) => {
    existingProjectId = publishParams.projectId;  // 👈
    console.log("Project ID", existingProjectId); // 👈
    expressImage.src = publishParams.asset[0].data;
    console.log("Image data", publishParams.asset[0].data);
  }
};

// Click handler for the Edit Design button
document.getElementById("editBtn").onclick = async () => {
  // Opening the existing project by ID
  let docConfig = { documentId: existingProjectId };
  // ...
  editor.edit(docConfig, appConfig, exportConfig);
};

Above, we're using existingProjectId to hold the project reference, collected in the onPublish callback every time the document is saved. Later, in the editBtn click handler, we're creating a new docConfig object passing the ID in the documentId property. This tells Adobe Express to look for an existing project and open it right away.

Logging the Project ID

Final project

We have all the required bits in place, but some simple refactoring is needed to keep the code clean.

You can check the entire embed-sdk-full-editor-tutorial project code as part of the dedicated embed-sdk-samples repository. Find the most relevant files below for reference.

<!-- CodeBlock -->

data-slots=heading, code
data-repeat=2
data-languages=JavaScript, HTML

main.js

import "./style.css";

// Importing theme and typography styles from Spectrum Web Components
import "@spectrum-web-components/styles/typography.css";
import "@spectrum-web-components/theme/express/theme-light.js";
import "@spectrum-web-components/theme/express/scale-medium.js";
import "@spectrum-web-components/theme/sp-theme.js";

// Importing Spectrum Web Components
import "@spectrum-web-components/button/sp-button.js";
import "@spectrum-web-components/button-group/sp-button-group.js";
import "@spectrum-web-components/divider/sp-divider.js";

// Importing the Adobe Express Embed SDK
await import("https://cc-embed.adobe.com/sdk/v4/CCEverywhere.js");
console.log("CCEverywhere loaded", window.CCEverywhere);

// Parameters for initializing the Adobe Express Embed SDK
const hostInfo = {
  clientId: import.meta.env.VITE_API_KEY,
  appName: "Embed SDK Sample",
};

// Prompts the user to log in only when exporting/saving the document
const configParams = {
  loginMode: "delayed",
};

// Initializing the Adobe Express Embed SDK
const { editor } = await window.CCEverywhere.initialize(
  hostInfo, configParams
);

// Will hold the project ID when a document is saved on Adobe Express
var existingProjectId = null;
var expressImage = document.getElementById("savedImage");

// Callbacks to be used when creating or editing a document
const callbacks = {
  onCancel: () => {},
  onPublish: (intent, publishParams) => {
    existingProjectId = publishParams.projectId;
    console.log("Project ID", existingProjectId);
    expressImage.src = publishParams.asset[0].data;
    console.log("Image data", publishParams.asset[0].data);
    // enable the editDesign button
    document.getElementById("editBtn").disabled = false;
  },
  onError: (err) => {
    console.error("Error!", err.toString());
  },
};

// Configuration for the app, shared by both Create and Edit flows
const appConfig = { selectedCategory: "media", callbacks };

// Configuration for the export options made available
// to the user when creating or editing a document
const exportConfig = [
  {
    id: "download",
    label: "Download",
    action: { target: "download" },
    style: { uiType: "button" },
  },
  {
    id: "save-modified-asset",
    label: "Save image",
    action: { target: "publish" },
    style: { uiType: "button" },
  },
];

// Click handler for the Create Design button
document.getElementById("createBtn").onclick = async () => {
  // Presetting the canvas size
  let docConfig = { canvasSize: "BusinessCard" };
  // Using the global appConfig and exportConfig
  editor.create(docConfig, appConfig, exportConfig);
};

// Click handler for the Edit Design button
document.getElementById("editBtn").onclick = async () => {
  // Opening the existing project by ID
  let docConfig = { documentId: existingProjectId };
  // Using the global appConfig and exportConfig
  editor.edit(docConfig, appConfig, exportConfig);
};

index.html

<body>
  <sp-theme scale="medium" color="light" system="express">
    <div class="container">
      <header>
        <h1>Adobe Express Embed SDK</h1>
        <sp-divider size="l"></sp-divider>
        <h2>Full Editor Sample</h2>
        <p>
          The <b>Create New</b> button launches a blank
          new project in a full editor instance. <br />
          Once you have published/saved a project, use the
          <b>Edit</b> button to resume editing the same project.
        </p>
      </header>

      <main>
        <img id="savedImage"
        src="https://placehold.co/300x300?text=Placeholder+Image"
          alt="Your design will appear here." />
        <sp-button-group>
          <sp-button id="createBtn">Create New</sp-button>
          <sp-button id="editBtn" disabled>Edit</sp-button>
        </sp-button-group>
      </main>
    </div>
  </sp-theme>

  <script type="module" src="./main.js"></script>

</body>

Next steps

Congratulations! You've implemented a Full Editor integration with the Adobe Express Embed SDK. You've learned how to create, edit, and let users export documents, as well as how to manage images between Adobe Express and your web application. What's next for you?

Footnotes

  1. A Webpack setup is entirely possible, but it requires manual (or semi-automated) steps to integrate the mkcert CLI and ensure proper HTTPS handling. We've chosen Vite to keep that out of the way and focus on the actual integration code. ↩