Sketch Plugin Project
Add to favorites
Sketch Plugin Environment and the Package Manager
Play video
Downloads for this Section
At the end of this section, make sure to download the finished project to compare your results.
Sketch Package Manager
To build a Sketch plugin, you may either comply with the directory structure and necessary files required to be interpreted by Sketch or use the SKPM (Sketch Package Manager) wizard-like command-line interface.
In this tutorial, we are going to rely heavily on the SKPM. This tool is distributed primarily through Node and its NPM (Node Package Manager). We strongly suggest you install it before going any further. After you get NPM on your machine, install SKPM by calling npm i -g skpm on the command line.
Creating the Project
You can use package manager to create a project. On a select folder for the project, run skpm create Angle or whichever name of plugin you might want. After creating a directory and fetching dependencies, the SKPM is going to prompt you to cd Angle to navigate downwards to the folder and begin development.
Other options will be presented to run, build and publish the plugin project. Don’t worry for now, by the end of this series you will use all of them.
Configuring the Development Environment
In the development videos, Visual Studio Code is being used as the development environment. Drag the plugin project folder into its icon to create a new window with the navigator set in the correct directory.
As much of your development is not going to happen on the interface, let’s toggle the integrated terminal using control+` or selecting View > Integrated Terminal on the menubar.
When running plugins, Sketch tries to be efficient by loading the plugin resources at once and avoids reloading them for performance. As this is not useful in the development environment, force it to reload the plugin scripts by running on the terminal:
defaults write ~/Library/Preferences/com.bohemiancoding.sketch3.plist AlwaysReloadScript -bool YES
With this enabled, every time you hit save on a script of your plugin, it will reload and fire on Sketch.
Running the Plugin
Every time you are developing a Sketch Plugin, you will be required to navigate to the project directory on the terminal and toggle the continuous regeneration by running npm run start.
This last command will build your project, start Sketch and immediately try to run the single line of code present in the default function of src/my-command.js which would be:
export default function(context) {
context.document.showMessage("It's alive 🙌");
}
Try to change the text given to the show message method and see it appearing on the screen.
Logging on the Console
Some of the development will not be UI related, so it is good to have a way to output data to the terminal. On VSCode, you can trigger a new tap on the Integrated Terminal using the + button. SKPM offers a handy command to listen to all logs done inside a running extension:
skpm log -f
Wherever you are in your scripts you may call log with an argument to output data. print("This works just like Swift's print");
Plugin Context
The plugin’s default function has a context in its signature. This variable is the current context in which the plugin was called, and it is a JavaScript Object that contains references to the JavaScript API, the current command, the active document, the plugin, the script path, the script URL and the current selection. Let’s use print on it to review its values:
print(context);
You will see that this dictionary returns a few types that are opaque to JavaScript such as MOJavaScriptObject, MSPluginCommand, MSDocument, MSPluginBundle. These object classes are bridged from Objective-C and they will require some taking care of to be worked with. More on that in the following sections.
Deconstructing the Context
It is JavaScript lingo to give descriptive function arguments using an options dictionary and deconstruct them on the other side. By placing a dictionary signature on the default function argument, the arguments will be automatically assigned from the dictionary.
export default function({
api,
command,
document,
plugin,
scriptPath,
scriptURL,
selection}) {
// Function definition
}
Selection
The first thing we should take care of is the selection. Angle is a plugin that gets a selection of a polygon or mockup and offers the user options of artboards to apply. You can see that most of this logic does not deal with all the complication of a perspective transform so let’s take care of getting those selections.
Using the R command in Sketch, draw two rectangles. Then, go back to the editor and write:
print(selection);
// This will show on the console
(
"<MSShapeGroup: 0x7fa1206f9ac0> Rectangle (C5AE2710-C237-4D25-81DE-2D9ED5751E11)",
"<MSShapeGroup: 0x7fa1204d9050> Rectangle Copy (F78DDA3C-0864-41CC-96F0-9AF71A15CAAC)"
)
Dealing with NSArray
On the console, you will receive an array of shapes you have just created. This array very ordinary because it can be accessed via indexes by using subscript notation such as: array[1]. Nonetheless, if you try to use the length variable, it will fail because this is not a JavaScript Array but an Objective-C NSArray. To get the length of an NSArray, you need to use the count method.
When writing JavaScript we will try to keep as far away as possible to using Objective-C constructs. In that thought, lets extend the JavaScript Array functionality by creating a function that translates NSArrays:
Array.fromNSArray = function (nsArray) {
let array = [];
for (var i = 0; i < nsArray.count(); i++) {
array.push(nsArray[i])
}
return array
}
Then, on the default function, write:
let selectedLayers = Array
.fromNSArray(selection)
print("🔷");
print(selectedLayers.length);
This newly created JavaScript Array gives us access to any Higher-Order Functions such as map, reduce, filter. These functions will come in handy when dealing with multiple selections and artboards and will be covered in a later section.
Getting Artboard from Page
The artboards to show on the dialog are the ones from the current document available on the context dictionary. After accessing them, we are going to transform them into a JavaScript Array for better handling.
let artboardsOnSelectPage = Array
.fromNSArray(document.artboards());
print("🖼");
print(artboardsOnSelectPage.length);
Notice that by using let in JavaScript you are ensuring that this is going to be the only variable with this name in the function scope. Different from Swift, this does not ensure value immutability.
Artboards from Other Pages
These last artboard we have listed are from the current page. To get artboards from other pages, we need to sequence the pages, filter the current page and include inside an array the artboards for each page.
let artboardsOnOtherPages = [];
let pages = Array.fromNSArray(document.pages());
pages = pages.filter(page => page != document.currentPage());
for (var i = 0; i < pages.length; i++) {
var artboards = Array.fromNSArray(pages[i].artboards());
artboardsOnOtherPages = artboardsOnOtherPages.concat(artboards);
}
The result will be a JavaScript Array of all the artboards in the document that are not on the select page. By keeping those separate, we can list the artboards on the select page before those on other pages on the dialog.
Configuring the Dialog
After getting the list of selections and all the artboards on the document, the next step would be to present the alert for the user to configure those options. Let’s create a function with which we are going to pass those variables:
function getSelectionAndOptions_forAngleInstances({ scriptPath }) {}
At this moment, we are going to leave this at showing the count of select objects and document artboards by creating an NSAlert and configuring its message.
let alert = NSAlert.alloc().init();
alert.setMessageText("Apply Mockup");
alert.setInformativeText("Choose an Artboard to apply into the selected shape.");
alert.addButtonWithTitle("Apply");
alert.addButtonWithTitle("Cancel");
When doing native interfaces, you have access to Cocoa classes such as NSAlert. They offer an Objective-C interface to JavaScript, such as the one we have just used.
return alert.runModal();
Placing an Icon on the Dialog
By default, an alert is going to inherit its icon from the application it is being called from, in this case, Sketch. On Angle, we are setting our own icon on the alert. Let’s create a load local image function to customize the alert.
function loadLocalImage ({ scriptPath, filePath }) {}
The icon required by NSAlert is an NSImage, and to get it from a bundle you will need to add the image file into the Context/Resources folder of your project so it can be accessed by the path of the script as follows.
let basePath = scriptPath
.stringByDeletingLastPathComponent()
.stringByDeletingLastPathComponent()
.stringByDeletingLastPathComponent();
return NSImage.alloc().initWithContentsOfFile(basePath + "/" + filePath);
Angle Logo
Before running modal on the alert, it is appropriate to call customize it with the icon with the dictionary as follows:
alert.icon = loadLocalImage({
scriptPath: scriptPath,
filePath: "Contents/Resources/logo.png"
});
Download the image for the Angle Logo and place it on your project inside the .sketchplugin bundle under Contents/Resources. In VSCode, you may disclose the bundle using the triangles. On Finder, you may right-click on the bundle and click the Show Package Contents.
Showing the Alert
It is JavaScript lingo to give descriptive function arguments using an options dictionary. As the matching pair of the object deconstructions, let’s write an options object as the argument of the function at the last line of the default function call:
getSelectionAndOptions_forAngleInstances({ scriptPath: scriptPath });
Conclusion
In this first section, we learned that Sketch exposes all it’s API to JavaScript and that it is possible to build native macOS UI using it. Nonetheless, we will have to be cautious when bridging from and to Objective-C. We have also set the environment and gathered the selection and the artboards on the file.
Next, we will define an Angle class and use it to grow the project and share code between the many ways to build a mockup.
Templates and source code
Download source files
Download the videos and assets to refer and learn offline without interuption.
Design template
Source code for all sections
Video files, ePub and subtitles
Assets
Videos
ePub
Subtitles
1
Sketch Plugin Project
Sketch Plugin Environment and the Package Manager
16:42
2
Angle Class
Using a Prototype to Reuse Code
20:04
3
Prototyping Perspective
Using Core Image to Prototype the Transform
7:25
4
Apply Mockup
Apply Perspective to an Artboard
17:15
5
Rotation and Mirror
Generate Stateful Commands
24:51
6
Working with Symbols
Investigating Sketch Classes
13:35
7
Dialog and Selections
Building a Cocoa UI to Handle Multi-Selection
31:10
Meet the instructor
We all try to be consistent with our way of teaching step-by-step, providing source files and prioritizing design in our courses.
Tiago Mergulhão
Interaction Designer
Pixel-crafting experiences for touch and click on a daily basis
3 courses - 15 hours

Create a Sketch Plugin
Overview of the Sketch Developer Portal by making you workflow even more productive using the plugin API
2 hrs

Swift Advanced
Learn Swift a robust and intuitive programming language created by Apple for building apps for iOS, Mac, Apple TV and Apple Watch
9 hrs

Learn Swift
Learn Swift a robust and intuitive programming language created by Apple for building apps for iOS, Mac, Apple TV and Apple Watch
4 hrs