CEP Guide Part 7: Packaging and Distribution

This post is part of the CEP Mega Guide series.

Now that the previous articles have covered everything I know about developing and testing HTML5/Node.js extensions to Adobe tools, all that remains is packaging and distribution (and then ruling the world, and so forth).


  • Extensions must be packaged into a simple format to be installed. This can be done with a command-line tool, or automatically with Extension Builder 3.
  • Packaged extensions must be signed with a certificate, but a self-signed certificate is fine in most cases.
  • The recommended way of distributing extensions is Adobe’s “Add-ons” repository. Distributing them directly works fine too, but is a bit less convenient for the end user.


Adobe tool extensions are packaged as “ZXP” files. Technically speaking a ZXP is just a zip of your extension’s source folder, with added signing details and the file extension changed to “zxp”.

Packaging from the command line

To package an extension folder, you can grab the “CC Extensions Signing Toolkit” command line tool from the Adobe Labs Extension Builder 3 download page (near the bottom). Invoking this tool is pretty straightforward:

For further details check the CEP documentation, p28. Incidentally right now there’s a gotcha – the command line tool currently doesn’t overwrite the output file if it already exists, so for a build script you’ll want to remove the output files before packaging. Here’s the script I use to package my extensions:

Continue reading


CEP Guide Part 6: Events

This post is part of the CEP Mega Guide series.

Now that we’ve covered calling APIs in the host tool, “all” that remains for building CEP extensions is knowing how to pass events back and forth. This is another epically long one, buckle up!


  • Passing events within and between extension panels is simple and easy. There’s also a very straightforward library for sending messages between extensions in different tools.
  • Several useful CEP or tool features are invoked by dispatching special events.
  • Sending events from the host tool VM to the panel VM works, but the details vary somewhat in different tools:
    • For ExtendScript tools, arbitrary events can be passed using a plugin (which is built into most, but not all, of the tools)
    • Flash and Photoshop each have a way to directly register for native tool events (“fileClosed” and so on) from the panel VM.
    • Outside of Flash and PS, it’s possible to register for a few native events; for others you might need to listen for them in the tool VM and then dispatch your own custom event.
Event passing within the Panel VM

All handling of events inside the panel VM is done with CSInterface.js (covered in Part 3 of this guide).

As simple as that. The CSEvent class referenced above is defined in CSInterface.js, so for further details it’s easiest to check the source.

The namespace for event IDs (i.e. "foo.bar"  in the code sample above) is global, so you can pass events between two different extensions just by matching up the IDs. To avoid unintentionally getting events from other extensions, it’s best to prefix event IDs with your extension ID:

Using Panel VM events

Besides defining your own custom events, there are a few useful built-in things you can do with events inside the panel VM. One is to catch UI theme changes. Many extension panels match their look and feel to the host tool, in order to look like part of the UI, but nowadays most Adobe tools let the user change the lightness/darkness of the interface. Catching this event lets you update your panel’s style if the UI theme changes.

Note that the theme colors aren’t part of the event object, you query them from CSInterface. (You’d probably want to do that at init time as well, to match the tool’s initial theme.) Here’s an outline of the code you’d need:

Continue reading


CEP Guide Part 5: Tool Integration

This post is part of the CEP Mega Guide series.

And so we reach the longest and most detailed part of the guide – how to actually make Adobe tools do stuff from an HTML panel. Taking a deep breath, and keeping the feet shoulder-width apart, here we go:


Each of the tools supporting CEP 5 has a built-in Javascript virtual machine for tool automation. However, these VMs are entirely separate from the VM that runs scripts inside an HTML panel. So if you have a Photoshop panel with a button that’s supposed to, say, open a new document, then the button’s event handler runs in one VM while the “new document” API lives in another. As such, tool integration for HTML panels is mainly a matter of bridging the gap between the two VMs.

In this series I’ll refer to the two JS engines as the panel VM and the tool VM. Architecturally, things look like this:


As shown, scripts in the tool VM can directly call internal functionality (like opening a new document). To do such things from the panel VM you pass code to the tool VM.

And speaking of the tool VM, there are two flavors: Flash Pro’s is called JSFL while all the other tools use ExtendScript. The distinction isn’t very important though – they both use standard Javascript and the specific APIs vary from tool to tool, even among the ExtendScript tools. For historic reasons it’s customary to use  .jsfl  and .jsx  extensions for scripts meant for JSFL and ExtendScript, but this isn’t required. (I recommend it though, as it’s easy to mix up which script is meant for which VM.)

Passing script to the Tool VM

Bridging the gap between the two VMs is done with the CSInterface class. (For the basics on CSInterface see Part 3 of this guide.) It has a handy  evalScript method, which takes a string and passes it over to the tool VM to be evaluated as Javascript. For example, to call alert()  from the tool VM, you can call code like this in the panel VM:


Note the different quotes used to wrap that command into a string literal. You can also get callbacks from the tool VM, if you call evalScript and pass in a function. In my extension work I found it useful to make a helper function that passes a script over to the tool VM, and writes the result to the console, thus:

Continue reading


CEP Guide Part 4: Working with Node.js

This post is part of the CEP Mega Guide series.


Node.js is a development platform built on Chrome’s Javascript engine. If you haven’t tried it yet (and I’m talking to my twin brother here), go get it, it’s awesome. Each Adobe tool that supports HTML panels has a built-in instance of Node that panels can interact with. Since Node has powerful core APIs and a massive ecosystem of 3rd party packages, it’s tremendously useful for extensions.

Calling Node’s core libraries

Rather magically, Node runs in the same VM as Javascript in your HTML panel. No setup is needed to call core libraries – just  require ‘em and use ‘em.

Adding third-party libraries (manually)

Calling external Node libraries works exactly the same as with built-in APIs (above), so all you need to do is add them to your project. To do this manually, just add the library to a folder called   node_modules in your extension source. For example, to open URLs in the system’s default browser, you could get the open module from npm, and place it thus:


Then you can require  it, thus:

Continue reading


CEP Guide Part 3: HTML Dev and Debugging

This post is part of the CEP Mega Guide series.

HTML Development

Since HTML panels internally use CEF for rendering, feature-wise they are largely equivalent to Chrome. Just like any modern browser, they support the standard web stack, including the flashy bits like WebGL and Web-RTC. To see it in action, try out this sample CEP extension, which includes a video chat demo and lots of other stuff.


So the main point here is, developing UI for a CEP extension is just like any other webdev project. There are no required tools or libraries – whatever you’d use for building a website will work.

With that said, there are a few edge cases that work differently for HTML embedded inside a panel. For example, calling   window.open(url, "_blank")  will open a new instance of CEF, rather than a browser window as you’d probably intend. For stuff like this where you go outside of pure HTML, it’s easiest to fall back to Node.js libraries, since there tends to already be a library for everything. For example, to open a URL in the system default browser I just used node-open. (Node.js integration is covered in part 4 of this guide.)

One other thing to be aware of is persistence. When the user closes and reopens a panel, in most cases the panel’s HTML will get reloaded. Flash is the exception here; its panels persist by default. There’s also a way to enable persistence in Photoshop – see Part 6 of this guide for details. Cookies work normally in CEP panels though, even when the tool is rebooted, so for long-term persistence that’s probably the easiest option.


Any Javascript run in your panel’s UI gets executed by a virtual machine specific to that panel. This VM is separate from the host tool or other panels, so all interaction with the host tool is done through CSInterface.js, a bridge library from the CEP team. CSInterface has APIs for:

Continue reading


CEP Guide Part 2: Getting Started

This post is part of the CEP Mega Guide series.


Since CEP 5 extensions are made out of HTML/Javascript/CSS, you can build them with nothing but a text editor (or whatever tools you prefer for HTML development). There are some optional tools you might find useful though:

  • If you plan to use Node.js you’ll probably want to install it locally. Technically you can build and test without doing this, but you’ll probably want to use npm or the REPL.
  • Adobe has an Eclipse-based IDE called Extension Builder 3, currently in beta. It has lots of conveniences – easy launching of extensions, an editing UI for the manifest, various Eclipse features, etc. If you’re familiar with Eclipse, I highly recommend it – if not, you might find doing things manually to be less trouble than learning Eclipse.
  • David Deraedt has a Brackets plugin that might be useful. It’s currently based on CEP 4; apparently CEP 5 support is in the works.

For the panel I built for an Adobe Japan promotion, I used Brackets and build scripts. I also used Edge Animate for the UI – since CEP 5 panels use standard, modern HTML, any typical toolchain should work fine.

Source Structure


At the bare minimum, a CEP 5 panel extension needs two files. First is an XML manifest, which must live at:   /CSXS/manifest.xml  (CSXS being the old name of CEP). Second is an HTML file, to be the panel’s UI. The HTML path is declared in the manifest, so it doesn’t have to be   index.html .

The manifest.xml File

A minimal extension manifest looks like this:

Continue reading


CEP Guide Part 1: Technical overview

This post is part of the CEP Mega Guide series.

CEP 5 Overview

The CC 2014 release in June 2014 saw a major update to CEP (Common Extensibility Platform), the extension framework inside many Adobe tools. What’s most interesting, though, is that CEP 5 is built entirely on web technology – the UI layer is buit with standard HTML5, all logic is written in Javascript, and Node.js (with its enormous ecosystem of libraries) is available behind the scenes. With CEP 5, it’s now extremely straightforward for a web developer to customize Adobe tools, or hook them up to other services or platforms.

Use Cases

There’s a huge value to having the ability to customize the tools one uses professionally. Obviously you can use CEP 5 any way you like, but personally I picture three main use cases:

  • To make yourself (or your company) more productive – by automating whatever is relevant to your unique workflow. For example, if you use Photoshop to edit textures for a game, a custom panel that knows how to package assets and launch a new local build might save a lot of time. (Especially on a big project where dozens of designers might use it..)
  • Integrating Creative Cloud tools to services or technologies beyond what Adobe has thought of. This could be as simple as posting to Twitter from Illustrator, or as complicated as controlling Photoshop with voice commands or LeapMotion (which works, by the way @_@ ).
  • Building your own authoring story. If your work involves any ad-hoc file formats or structured data that’s hard to create visually, a CEP extension might be enough to turn Photoshop or Flash into your own custom authoring tool.

Here follows a brief look at the technology stack behind CEP 5 – each topic will be covered in depth in the rest of the series.

There are currently eight supported tools: Photoshop, Illustrator, Flash Pro, Premiere Pro, After Effects, Prelude, InDesign, and InCopy. In all cases, HTML panel support was added in the most recent major version (the CC 2014 release from June 2014).

The moving parts inside a CEP 5 extension are straightforward:

  • A manifest.xml  which declares the extension’s title, version, supported tools, etc.
  • HTML content (to be the extension’s UI)
  • Node.js modules (such as you’d get from npm)
  • Scripts to be executed by the host tool
  • Other assets (panel icons, UI assets, or whatever other files the extension might use)

In the minimal case, you can get by with just   manifest.xml  and   index.html .

To render an extension’s HTML, each panel uses an embedded instance of Chromium (i.e. CEF), so the UI layer is basically no different from your desktop browser – even very modern HTML features work as you’d expect. Likewise, each tool supporting CEP 5 has a built-in Node.js implementation, so extensions can use Node even if it’s not installed on the user’s machine (or the developer’s, for that matter).

For tool integration, each of the Adobe tools contains a Javascript virtual machine that can see the tool’s internal DOM and APIs. For Flash this is JSFL, and for all other tools it’s ExtendScript. Finally, since the UI uses Chromium, debugging extensions is easy – it’s done through an inspector that’s exactly like the developer tools in each major browser.


Customizing tools like Photoshop and Flash with nothing but web technology might sound surprising, but in practice it’s quite accessible for any web developer, and well worth the effort if you use Adobe tools (or your company does).

Next up is Part 2: Getting Started, which covers minimal source code and the steps required to run an extension.


CEP 5 Super mega guide: Extending Adobe apps with HTML5+Node.js


It’s not that widely known yet, but ever since the CC 2014 updates in June of this year, eight different Adobe tools now support a common extension framework based purely on web technologies. The framework, called CEP 5, uses panels defined in HTML5 backed up with the wondrous power of Node.js.

In short: anyone who’s comfortable with Javascript can now customize Adobe tools in unbearably awesome ways:


I’ve now built a couple of projects with this, so I thought I’d write up everything you need to get started. (This guide was first published in Japanese – here, if you’re interested.) I call it:

CEP 5 Super Mega Guide Series!

If you’d rather start with the code, here is a sample CEP extension – a self-contained custom extension that implements most of what’s described in this guide. Right now it’s commented in Japanese, but code is code, hey? I’ll put up an English version at some point. To run, just download it and then follow the steps in the “Testing extensions” section of Part 2 of the guide.

First off is Part 1: Technical overview





  • エクステンションを他の人がインストール出来る状態にするにはパッケージが必要。コマンドライン、またはAdobe Extension Builder 3で出来る。
  • パッケージに証明書が必要となるが、通常の場合には自分で作るもので十分。
  • お勧めする配布方法は、アドビのAdd-onsレポジトリ。しかしパッケージされたファイルを好きなように配布する手もある。




エクステンションフォルダーをZXPにパッケージするには、「CC Extensions Signing Toolkit」と言うコマンドラインツールがある。Adobe LabsのEB3ページでダウンロードできる(EB3の下に)。使い方は割りとシンプル:

Continue reading



本記事はCEPスーパーメガガイドのPart 6です。



  • パネルVM側でのイベント処理は簡単。パネル同士、エクステンション同士、ツール同士のイベントやり取りを出来るし、仕組みはツールによって変わらない。
  • ツール側からパネルVMへのイベントはツールで異なる:
    • ExtendScriptに対応するツールでは、Pluginを使ってカスタムイベントをパネルに渡せる。
    • FlashとPhotoshopの場合、ツールの多くのネイティブイベント(ファイル編集など)をパネルから直接取得できる
    • Flash・PS以外のツールではいくつかのネイティブイベントをとれるが、場合によってはツールVM側で取得してからカスタムイベントとしてパネルに渡す必要がある

パネルVMで出来るイベント処理は全てCSInterface.jsにある。(CSInterfaceの概要についてはPart 3まで)


エクステンション同士のイベントは、デフォルトの仕組みである。イベント名の名前空間はグローバルなので、イベントの type さえ一致すれば他のエクステンションに渡せる。イベント名が被らないように、IDをプレフィックスするのがお勧め:



Continue reading

technical evangelist, Adobe Japan