Edit in GitHubLog an issue

Creating your first UXP-based Photoshop plugin

In this tutorial, you will create your first own Photoshop plugin using UXP.

Prerequisites

To follow this tutorial, you need Photoshop v23 or above and the UXP Developer Tool (UDT). You can install both applications with the Creative Cloud Desktop app. You also need basic knowledge of HTML and JavaScript.

Step 1: Create the plugin

Open the UXP Developer Tool and click the "Create plugin..." button. In the dialog that opens, enter the following details:

FieldValue
Plugin Name
My first plugin
Plugin Id
my.first.plugin
Plugin Version
1.0.0
Host Application
Adobe Photoshop
Host Application Version
23.0.0
Template
quick-layers-starter

Click "Select Folder" and select a new, empty folder where you want to develop your plugin. The Developer Tool creates the necessary files in your selected folder and adds the plugin to the list of plugins.

You should now be able to see the following files in your selected folder:

  • icons: a folder containing a set of icons for your plugin
  • index.html: your plugin's entrypoint. This gets loaded when the plugin loads
  • manifest.json: a file containing the metadata you specified in UDT as well as a pointer to the index.html as an entrypoint.

As well as some other "meta" files like LICENSE, README.md, etc.

Step 2: Run the plugin

Open Adobe Photoshop and create some sample file you can use with your plugin.

To run your plugin within Photoshop, click the "•••" button on the right of your plugin's row within the UDT and select " Load". This loads your plugin in Photoshop and automatically opens the plugin's panel.

The quick-layers-starter template initially contains a panel with a "Populate Layers" button that allows you to populate a box within the panel with the layer names:

A Photoshop panel with a list of layer names and a button called "Populate Layers"

Let's take a look at what's going on in the background when running this plugin.

In the manifest.json file, the "main" field points to the index.html file:

Copied to your clipboard
1{
2 "id": "my.first.plugin",
3 "name": "My first plugin",
4 "version": "1.0.0",
5 "main": "index.html",
6 "host": [
7 /* ... */
8 ],
9 "manifestVersion": 4,
10 "entrypoints": [
11 {
12 "type": "panel",
13 "id": "vanilla",
14 // [...]
15 "icons": [
16 // [...]
17 ],
18 "label": {
19 "default": "Starter Panel"
20 }
21 }
22 ],
23 "icons": [
24 // [...]
25 ]
26}

When Photoshop loads the plugin, it loads the index.html file specified here. The index.html file, in turn, defines our panel's UI:

Copied to your clipboard
1<!DOCTYPE html>
2<html>
3 <head>
4 <script src="index.js"></script>
5 </head>
6 <style>
7 /* [...] */
8 </style>
9 <body>
10 <sp-heading>Layers</sp-heading>
11 <sp-body id="layers"> No layers </sp-body>
12 <footer>
13 <sp-button id="btnPopulate">Populate Layers</sp-button>
14 </footer>
15 </body>
16</html>

As you can see, the index.html file then loads the index.js.

The index.js file then sets up a click listener on the "Populate Layers" button and uses the Photoshop API to populate the <sp-body id="layers" /> element with the layer names:

Copied to your clipboard
1function showLayerNames() {
2 const app = window.require("photoshop").app;
3 const allLayers = app.activeDocument.layers;
4 const allLayerNames = allLayers.map((layer) => layer.name);
5 const sortedNames = allLayerNames.sort((a, b) =>
6 a < b ? -1 : a > b ? 1 : 0
7 );
8 document.getElementById("layers").innerHTML = `
9 <ul>${sortedNames.map((name) => `<li>${name}</li>`).join("")}</ul>`;
10}
11
12document
13 .getElementById("btnPopulate")
14 .addEventListener("click", showLayerNames);

Note that you can use the window.require() function to import various API modules, like require('photoshop') in this example.

Step 3: Adjust the plugin

We could call this good enough, but let's face it: This doesn't feel like you've built your own plugin. So let us at least add some customization to it by adding additional information about our layer to the output.

Have a look at the Layer class API Reference. This page lists all the properties and functions available on a layer object. You can choose whatever property you want, but for this tutorial, we will just use the opacity: number property.

Adjust the main.js to also include the new property in the output:

Copied to your clipboard
1function showLayerNames() {
2 // [...]
3 const allLayerNames = allLayers.map(
4 (layer) => `${layer.name} (${layer.opacity} %)`
5 );
6 // [...]
7}
8
9// [...]

With your main.js file saved, you need to reload the plugin to run the plugin including your changes. You can do this by selecting the "••• > Reload" option in the UXP Developer Tool.

Alternatively, you can also watch your plugin folder for changes to reload the plugin automatically whenever you change something. To do so, run the "Watch" option in your plugin actions menu in the UDT.

Back in Photoshop, when you click "Populate Layers" again, you should see that your property is now also included in the output:

A Photoshop panel showing a list of layers including their opacity and a button called "Populate Layers"

Also, you may find the icon missing when docking the plugin panel in a toolbar. It can be resolved by changing "path" field to the updated icon filename in manifest.json. For example, "path": "icons/dark.png", corresponds to following icon files

screenshot of a file structure. The folder icons contains two files: "dark@1x.png" and "dark@2x.png"

Next steps

You've now built your first own plugin. It doesn't look like much right now, but by taking a look at what's available in the API Reference, you can already do a lot of things with the knowledge of this tutorial, alone.

In the next tutorial, you'll learn how you can not only get information about your document, but actually make changes to it, as well.

  • Privacy
  • Terms of Use
  • Do not sell or share my personal information
  • AdChoices
Copyright © 2024 Adobe. All rights reserved.