📜 ⬆️ ⬇️

Sketch + Node.js: generate icons for multiple platforms and brands



There is nothing easier than adding an icon to the project: you just need to write to the designer, he exports it from Sketch and sends you the desired option, and you use it in your code. If you have a dozen projects, several platforms and many A / B tests for design, then all you have to do is to do the same, only 40 times more often and never make mistakes ... or try to automate the process. Under the cut - the first part of the translation of an article by my colleague Cristiano Rastelli about one of the examples of such automation.

Problem we solved


We at Badoo are developing a dating app. In fact, there are several applications, each of which operates on several platforms ( iOS , Android , Mobile Web , Desktop Web ), and several teams are working on them.
')
When developing we use hundreds of different icons. Some are the same in each application, others correspond to a particular brand. Sometimes the design changes, and with it the icons change: new ones appear, some are updated, some are deleted (but often remain at the same time in the code base).

The creation and maintenance of icons is done by our design team, and when the icons are ready for work, designers usually send them by email, chat or cloud. This not only took time, but often led to errors. To be honest, there were mistakes every time (we are all human): sometimes the icons were updated on one platform, but they were not updated on another, sometimes they disappeared or did not match the format or size. Therefore, designers and developers were forced to be in constant contact; The developers exported the icons directly from the Sketch-file, and those were added to the code base, but checks for the presence of similar, reusable icons in the database were not carried out. I am sure you understand well what I am talking about.

We in Badoo have a design system called Cosmos , and recently we introduced a multiplatform (Mobile Web, Android and iOS) library of tokens . In essence, now changes in the design (for example, the appearance of the button border, the background color of the page, the size of the title, or the duration of the animation in a pop-up window) can be described using a set of parameters that are then automatically exported and used in all applications on all platforms.

Our solution, which in a short time in a few clicks to transform design ideas (for example, color change) into a functioning code, impressed our product managers and designers equally. Therefore, their next question (and at the same time the task) was: “Is it possible to do something similar for resources?” We answered: “Yes, you can (probably)” .

I must admit that at first we acted blindly. We had a few ideas, but given all the restrictions, we were not sure that they would work. We decided to start with MVP, but everything went so well that the project became our final product with all the necessary functions.

Requirements


The requirements for the MVP project were clear: a tool that would receive a Sketch file at the entrance, and at the output would produce all the icons in all the formats we needed and would support variations of icons for A / B tests.

The difficulty was that the same icon has different parameters (color, shape) depending on the brand. Below are a few icons for our applications. As you can see, some are absolutely identical, others differ in a number of parameters, and still others have nothing in common.



Please note that the colors used in the icons are not just colors: they correspond exactly to the colors of the brand and specific features specified in the tokens .



So, in developing the tool, our goal was not only to automate the creation and delivery of icons for different platforms and brands, but also to make possible their dynamic colorization in accordance with the brand.

Sketch and SketchTool


Sketch is the main tool of our designers. And, although we considered other options (for example, Figma ), we knew that within the framework of this project we would use files in Sketch format (because our designers own this tool best and all our current icons and resources are saved in this format) .

In fact, at the beginning of the project, we were not even sure which file format is needed for the platforms. We imagined the process like this: export icons from a sketch file in SVG format, then feed SVG files to versions for a mobile browser and Android, and for iOS find a library that converts SVG to PDF. Such a plan was originally, although we had no idea whether our idea would work and what problems we might face. In essence, for this we needed MVP - to understand whether we are implementing our project, and, if so, how time-consuming it will be.

I don’t know if you had to work with PDF converters, but my experience says that this is a nightmare. They almost always do the job, but they never do it 100%. Therefore, the spinal cord, I felt that we were going on a slippery slope.

Exporting resources from Sketch is perfect - I have never had problems uploading SVG, PDF or any other formats. Therefore, I decided to find out whether it is possible to interact with Sketch in a different way — export resources directly through Sketch, perhaps programmatically (I was also interested in whether it was possible to create a custom plugin, although this would mean a work car for me who does not have such experience) .

I knew that the internal structure of the sketch file is essentially an archive. By renaming .sketch to .zip, you can double-click to open the file; in the resulting folder you will see a list of JSON-files and a preview file in PNG format.



So, I began to study JSON files in an attempt to understand how they are related to each other.

I found that, although they have a large degree of nesting (and large in size), the relationships between different entities within objects are not so confusing. You have pages, artboards, and layers. Inside each layer there are paths that may have common styles. Each of these entities has a unique ID that allows you to keep the connection between different files; and all pages are stored in JSON files and are contained in the pages subfolder (the page ID is the name of the file).

In the process of studying, I made an important discovery: the names of layers, pages and styles are just labels that can be changed at any time without disrupting the work of the internal structure of a Sketch file . All that matters is the unique ID associated with them, which is not shown to the end user (although it can be read and referenced to it within JSON files). Here is a sample of what a unique style ID looks like:

{ "_class": "sharedStyle", "do_objectID": "49BA4E98-8D63-435C-81D9-E2F6CDB63136", "name": "name-of/the-style", "value": {     "_class": "style",     "endMarkerType": 0,     "fills": [         {             "_class": "fill",             "isEnabled": true,             "color": {                 "_class": "color",                 "alpha": 1,                 "blue": 0.7176470588235294,                 "green": 0.4627450980392159,                 "red": 0             },             "fillType": 0,             "noiseIndex": 0,             "noiseIntensity": 0,             "patternFillType": 1,             "patternTileScale": 1         }     ],     "miterLimit": 10,     "startMarkerType": 0,     "windingRule": 1 } } 

Therefore, I thought about the possibility of entering agreements on the naming of artboards and pages in order to communicate in this way some kind of meta information about the relationship of resources and use them programmatically during assembly.

Sketchtool


Thus, when the primary research was completed, the plan “Exporting icons to SVG and then converting ” turned into “ Let 's make a Sketch plugin that will allow you to directly export icons in the final format” . However, even then the scheme of work was rather vague (and not the fact that it was realizable).

Studying the source code of existing plug-ins, I tried to understand if they could interact with the Sketch export API, and, if so, how. And at that moment I came across a tool that I hadn’t heard about before - SketchTool.

SketchTool is the official Sketch tool (that is, developed by Bohemian Coding). According to the documentation, he
is a command line utility that comes with Sketch and allows you to perform certain actions with documents in Sketch format, such as checking or exporting resources. It also allows you to manage certain Sketch functions from the command line — for example, running plugins.

Wait, a command line utility that allows you to export resources ? Exactly what is needed! In addition, since this is an official tool, there should be no problems with version compatibility, obsolescence, support, etc.

I began to study the utility and read all the documentation - the only page on the Sketch site (there are very few materials on the Internet, so it’s not surprising that I heard about it just now).

SketchTool is attached to Sketch, and can be found at: Sketch.app/Contents/Resources/sketchtool/

Having $/Applications/Sketch.app/Contents/Resources/sketchtool/bin/sketchtool command $/Applications/Sketch.app/Contents/Resources/sketchtool/bin/sketchtool , you will get the following result (I simplified the data a bit):

 Usage: sketchtool <command> [<args>] [--formats=<string>] [--use-id-for-name{=YES|NO}] [--export-page-as-fallback{=YES|NO}] [--serial{=YES|NO}] [--context=<string>] [--application=<path>] [--without-activating{=YES|NO}] [--item=<string>] [--items=<string>] [--safemode{=YES|NO} | --no-safemode | -S {<YES|NO>}] [--max-size=<float> | -m <float>] [--background=<string> | -g <string>] [--compression=<float> | -c <float>] [--new-instance{=YES|NO}] [--reveal{=YES|NO}] [--timeout=<float>] [--include-symbols{=YES|NO}] [--bounds=<rectangle>] [--outputJSON=<path>] [--filename=<string>] [--wait-for-exit{=YES|NO}] [--scales=<path>] [--overwriting{=YES|NO}] [--group-contents-only{=YES|NO}] [--trimmed{=YES|NO}] [--help] [--progressive{=YES|NO}] [--save-for-web{=YES|NO}] [--output=<path>] Commands: dump               Dump out the structure of a document as JSON. export artboards  Export one or more artboards export layers     Export one or more layers export pages      Export an area from one or more pages export preview    Export a preview image for a document export slices     Export one or more slices help              Show this help message. list artboards    List information on the document's artboards. list formats      List the supported export formats. list layers       List information on all of the document's layers. list pages        List information on the document's pages. list slices       List information on the document's slices. metadata          List the metadata for a document. run               Run a command from a plugin, inside Sketch. show              Show the location of the various sketch folders. See 'sketchtool help <command>' for more information on a specific command. 


As you can see, the tool has four main functions:

read/dump - read / dump the metadata of internal JSON files,
list - create a list of file entities,
export - export these entities,
run - run the command provided by the plugin.

In addition, each team has several options available. In the case of export, almost all options that can be found in the corresponding panel are also available on the SketchTool command line:



This means that SketchTool allows you to use Sketch directly for exporting (for example, from SVG to PNG or PDF) without using external converters. Gorgeous!

A quick test using SketchTool and a regular sketch file with several icons inside confirmed our guesses: thanks to this simple tool, we can not use external programs for export and not write our own. Sketch can do anything!

Sketch File (s)


When we decided that we would use Sketch both for storing and exporting icons, it was time to collect the icons used in our applications into a Sketch file.

Initially, we planned to work only with a limited set of icons created for the MVP project, but we quickly realized that it would be better to collect them all - in order to immediately eliminate duplication, inconsistency and other problems.

Our designers did a good job - and after a couple of days, most of the resources used by them in the Sketch files were compiled into one file. At this stage, he looked like this:



Each icon in the file had its own artboard, named according to the desired icon name (later on, the same name Sketch will give the resulting file to the resource export). All paths are converted to contours, and the combined paths are reduced to one shape. Due to this, the generated resources retain an ideal appearance (as in the source file) and are compatible with various platforms.



Dynamic colorization of icons using common styles (and token design)


The next step after collecting the icons was to apply the right colors to them. We created a set of predefined common styles ( Shared Styles ) in Sketch, the names of which corresponded to the names of the tokens of our design system , and then used them to color the icons.

Here is an example of how a style is applied to a specific layer:



This is how styles are declared and then applied to the element:



The key is the naming convention. Designers can manage styles in any subfolders: the name of the style is given by the name of the corresponding token for this color. Thus, subsequently the build script can programmatically operate with them.

The names of the pages and artboards used for A / B testing


It's time to understand how to allow designers to conduct A / B testing of icons. Again, we decided to resort to a naming convention (I'm a big fan of the KISS principle).

In this case, we used the names of the pages to determine the test set (using the XP_ prefix), and the names of the arbords — to determine which resource the A / B test belongs to and which of its variants (indicated in square brackets).



The names and variants used for the test were not invented by us - they must match the unique IDs assigned to the tests and variants in our own split-testing tool. Thus, resources can subsequently be correctly mapped to a specific user group.

Multiple files for multiple brands


The last thing that interested us was how to support different forms of the same icon for different brands?



Compliance with this requirement was very important for our product managers, and we had several options. First, we wanted to use different pages of the same Sketch file, which would be named according to the brand. But soon they realized that it would complicate the life of the designers: it would be difficult for them to constantly synchronize the icons of different brands. So we decided to use several files: a common file , where all the icons that do not change depending on the brand, and files for each brand , which would replace the “basic” icons from the common file , will be stored.



Our sketch files are ready! Came the turn of writing code.

Translator's note: As I said, the article consists of two parts, and this is the first part of the translation. The second will appear on our blog in a few days. Thanks for attention.

Source: https://habr.com/ru/post/441898/


All Articles