Extending Adobe CC 2014 apps

Using HTML5 and Node.js

On June 18 2014, Adobe introduced Creative Cloud 2014. As you would expect, there were many changes and updates, both large and small, visible and kind-of-hidden.

One of the hidden changes is the introduction of the Common Extensibility Platform (CEP) 5.0 in many of Adobe’s apps. CEP (also known as CSXS) is a software component that is shared among many of Adobe’s apps, and provides software developers with a way to use HTML5 based technology to extend and customize the applications.

With Creative Cloud 2014, Photoshop, InDesign, InCopy, Illustrator, Dreamweaver, Flash Pro, Premiere Pro, Prelude and After Effects all include CEP 5.

CEP 5 is a major update that provides capabilities that far surpass its predecessors. A key feature is the integration of Node.js which practically means you can use Node’s rich APIs as well as third party NPM modules within Adobe’s products.

Node and its massive ecosystem of 3rd party modules are now at your fingertips.

Would you like to connect Illustrator with a database? Check. Read and write files within After Effects? Check. Remote control InDesign via a smartphone app? Check. Send and receive email? Check. Compress data? Check. Encrypt data? Check. Visualize data? Check. Use the command line? Check Integrate Photoshop with Flickr? Check. Twitter? Check. Facebook? Check. Amazon Web Services? Check Digital Asset Management systems? Check Should I stop now? Check

How to use Node.js APIs in Adobe products

For a detailed discussion about how to set up a new CEP project, read this guide. Although the guide is about setting up a CEP 4 project, it is still relevant. A few things have changed as I will describe below.

First of all, HTML5 extensions live in one or more of the following folders:

  • All users, Win: C:\Program Files (x86)\Common Files\Adobe\CEP\extensions
  • All users, Mac: /Library/Application Support/Adobe/CEP/extensions
  • Per user, Win: C:\<username>\AppData\Roaming\Adobe\CEP\extensions
  • Per user, Mac: ~/Library/Application Support/Adobe/CEP/extensions

The bare-bones project structure is simple and looks like this:

CEP provides a few JavaScript APIs, which you can get from the Adobe CEP site on GitHub. First and foremost is CSInterface which provides the interface to interact with the host application. You can also use Adobe IPC to support cross-extension and cross-app communications.


The manifest.xml file sets the metadata for the extension. To be able to use Node, you need to target the right version of CEP and the Adobe product. For example, this sample manifest file will make the extension support the Creative Cloud 2014 versions of Photoshop, InDesign, InCopy and Illustrator. (Highlighted bold where the file differs from prior CEP versions)

<?xml version=”1.0" encoding=”UTF-8" standalone=”no”?> <ExtensionManifest ExtensionBundleId=”com.example.mynodeextension” ExtensionBundleName=”My Node Extension” ExtensionBundleVersion=”1.0" Version=”5.0">
<Extension Id=”com.example.mynodeextension.extension” Version=”1.0"/> </ExtensionList> 
<ExecutionEnvironment> <HostList>
<Host Name=”IDSN” Version=”[10.0,10.9]”/>
<Host Name=”AICY” Version=”[10.0,10.9]”/>
<Host Name=”ILST” Version=”[18.0,18.9]”/>
<Host Name=”PHXS” Version=”15.0"/>
<LocaleList> <Locale Code=”All”/> </LocaleList> <RequiredRuntimeList> 
<RequiredRuntime Name=”CSXS” Version=”5.0"/> 
</RequiredRuntimeList> </ExecutionEnvironment> 
<Extension Id=”com.example.mynodeextension.extension”> <DispatchInfo> 
</Resources> <UI> 
<Menu>Hello world</Menu> 
<Size> <Height>400</Height> <Width>400</Width> </Size> 
</Geometry> </UI> 
</DispatchInfo> </Extension> 
</DispatchInfoList> </ExtensionManifest>

To use a Node.js API, all you need to do is to add a require statement in your JavaScript file.

For example, to use Node.js HTTP API, this is what you add:

var http = require(‘http’);

Likewise, to use Node.js FileSystem APIs you simply add:

var fs = require(‘fs’);
You don’t need to install Node.js on your computer. It’s already included the Adobe app and the extension will automatically include the right Node.js library.

How to use NPM APIs in your extension

To include an NPM is simple. In your extension folder, create a folder called node_modules:

Place your NPM in the node_modules folder.

Then, add a corresponding require statement in your JavaScript code just like you did for the Node.js APIs. For example, if I’m using the FeedParser NPM, I’ll add this statement:

var FeedParser = require(‘feedparser’);

That’s all there is to it.

Useful bits of information

Most of the built-in APIs in Node.js are available for use in HTML5 extensions, with a couple of exceptions:

  • Cluster APIs are not supported.
  • Console APIs are not supported on Windows.

CEP does some tricks behind the scenes to get Node integrated. In some cases, the tricks can interfere with some JavaScript frameworks.

First of all, CEP injects following symbols into the root HTML DOM:

  • global, GLOBAL, root, window
  • Buffer — Node’s Buffer class
  • process — Node’s process class
  • require — the magic function that bring you the Node API
  • module — in Node, for compatibility reasons the main script is a special module

CEP and 3rd party require functions

If your app uses libraries like RequireJS that insert a require function into the DOM, you should consider renaming CEP’s require function to something else before migrating. The following code should do the trick.

<script type=”text/javascript”>window.nodeRequire=window.require && window.require=undefined</script>
<script type=”text/javascript” src=”your/require/js/file.js”></script>

CEP and 3rd party module functions

If your app uses JQuery that is trying to register itself as Node.js plugin, you will have to add the script below inside the script tag to define window.module as undefined.

<script type=”text/javascript”>window.module = undefined</script> 

Disabling Node.js APIs in an iframe
CEP provides an option to disable Node.js APIs in an iframe. To do so, add a nodejs-disabled=”true” attribute to iframe tag. For example:

<iframe id=”xxx” class=”xxxxx” nodejs-disabled=”true”>

Setting the RequireJS environment

The RequireJS’s text plugin tries to detect what it should load and use for text resources. If you encounter a problem with that, check this page.

Adobe CEP Sample extensions

Head over to the CEP Samples repository to try CEP5 samples. For a sample that shows how to use the above features, take a look at the RSSReader sample.

For more resources, head to the Adobe CEP home.

You can also follow me on Twitter.

Show your support

Clapping shows how much you appreciated Hallgrimur Bjornsson’s story.