JSON to Figma Plugin. How to create a vanilla Figma Plugin
Sup, dudes! This is your boy Mr.Smarty Pants! Today I want to break down the process of writing a Figma Plugin. In our case, it will be a plugin that can parse a JSON file and populate text layers by its values.
For the introduction — here is a plugin’s website:
and the plugin's community page:
If you don’t have a test JSON file you can download it here:
The Idea
I decided to create a plugin when I was working on the new “Team” page for the website and I wanted to use real names and positions of my co-workers but I didn’t have time to rename each layer in each card for every variation of the page. I was looking for the plugin that can take real data from JSON files.
So, I checked currently available Figma plugins and didn’t find anything that fits my needs:
- Parse local JSON files
- Ability to change a text without selecting layers directly, but select only selection, groups or frames with these layers (because I had more than 30 cards and selecting these layers manually could be time-consuming).
I also wanted to parse images URL’s, fetch them and paste as a fill.
I want to create a plugin, what should I do next?
The first step and the easiest way to create a plugin is to create a boilerplate in Figma.
Right now there is a bunch of different templates and boilerplates to make a plugin on React or Vue js but the fastest way is Vanila JS + Plain HTML + CSS. Of course, this approach has its inconveniences like — everything will be in one file, you can’t separate it like when you work with a framework like React for example.
1. Create a boilerplate
Figma has a very good setup guide page about how to create a plugin:
- To create your plugin → right-click → Plugins → Development → New Plugin…
2. In this case, we will get the template with UI, the second option will run the plugin once without interaction with a user, so do not forget to choose the third option.
3. Create a name for your plugin
These things you should not forget — do not forget to install NodeJS:
Download | Node.js
Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine.
nodejs.org
Install package managers like npm or yarn:
and Typescript sudo npm install -g typescript
and VisualStudio IDE as well
But don’t worry, Figma will tell what to do at the end of the plugin setup.
In this template, we should pay attention only to these two files code.ts
and ui.html
:
The connection between these two files — is messaging —we send a message from UI (ui.html) to API (code.ts) and vice versa:
2. Wireframing
I started from wireframes/design of the plugin. This is an important part to understand how everything should work, otherwise, you risk to forget or miss a step or corner case in your flow.
Design is simple but representative. But even if your design will have a super-simple design, don’t do the coding from design. Start your coding from the logic, make sure that what you want to do is possible to make first and only then you can care about decoration.
3. Coding
So, we have two parts here — UI and API logic. In this particular case, we will send messages only from UI to API.
Plugin Structure
The UI.html file is pretty simple, we have an HTML section, CSS, and the JS part in this file. Basically, all we want to do we set here and then translating the user’s choice to API.
And an example of how we translate a message from UI to API:
I will skip the part of how I made features like drag`n`drop for files and then cut it. To make my first plugin version faster and with minimal efforts, I decided to add additional features in the next version. I also cut off the image featuring from URLs feature, because I wasn’t happy with the result — images were sometimes uploaded in the wrong order. So, right now let me show only parts that I eventually left in the plugin.
Note: all assets should be stored somewhere, you can’t load local assets from default plugin template.
First, let’s take a look at the plugin UI structure to understand for which parts we will write JS functions:
JS in UI.html
// Variables for UI elements
I’ll start to write the code from declaring variables of our HTML sections and elements:
// Util Functions Block
Then a block of util functions — functions that can be used outside the context and can be reused in different places.
getElementsHeight() function
A simple function to get the height of an element
shuffle() function
With this function, we can shuffle in a random order any array.
checkForNestedObj() function
Not an ideal function, and probably I’ll rewrite in a more optimized way, because of its size and certain restrictions. Right now we are checking JSON for nested objects up to the second level and merge them into one property.
We turn this object:
into this one:
// Load and read a JSON file
onReaderLoad() function
The bigger part here is changing styles— we hide the initial screen when a file was uploaded and show the hidden section. Then we take the JSON file and run it in mapToButtons()
function—to create buttons from JSON keys like name
, position
, email
etc. Then we push the message to API, change the plugin frame size — to get the height automatically we use util function getElementsHeight()
.
Also, I didn’t add any in-plugin feedback for errors here and if a user will load not a JSON file the user will see the native Figma error message.
// Create Buttons
createStringButtons() function
In this function, we create a button with the name of the JSON key and depending on populate option — populate selected layers, by name or string templates push a message to Figma API.
mapToButtons() function
This is the second part of the button creation. In this function, we are map all keys that we have in the JSON file and create as many buttons as we have in the JSON.
// Handlers
onChange() function
Here we watch for changes in file input and if we detect these changes (file load) we take the file and parse it.
showFileStructureClick() function
This function is pretty simple and doesn’t do anything important for the plugin only shows/hide a section with the preferred JSON file structure.
// Reset file
This is the last function in UI.html and this function resets the plugin. We set all styles and elements to their initial conditions.
JS in code.ts
The first part of the code here is variables for the initial width and height of the plugin’s frame. And a small function fillTextNodes()
that we will use later — in this function, we take the selection array and map it, we are going through each selected text-layer in our selection array and if there is a match in our JSON (if the amount of the selected items is equal or less then in the JSON) we replace the current string with a new one.
After that, we are setting up params for the plugin UI — the width and the height variables.
And the main function here is when we receive a message from UI.html.
a. If we get the change-size
or reset
message we change the size of the plugin frame.
b. Then if message types not change-size
and reset
and the amount of selected layers is less than 0 we show an alert message “Please select layers”. In this case, I use in-app-message that Figma provides alert()
.
c. Here if the array of selected layers is more than 0 we can do something in our case we check for one of three messages — only selected layers, populate by layer name and string templates. And if the message is selected-text
we use the fillTextNodes()
function.
d, e. If the message is string-template-text
. We don’t need to directly/manually select layers to populate them. And what interesting here is recursion —we check selected items until there will be only layers and not an array if we see an array we understand that it could be a group or a frame and we’re going deeper into it—trying to find layers. Then in the text layer, we check if a string contains a {string template} with this method item[key].includes({${string template name}})
. That how this function works:
f, g. Basically it's the same function as getAllId()
but here we check not the text of the layer but its name and if the name matches we replace the text of this layer.
That it. It might be not so detailed explanation, but I just wanted to break through the structure and general things of this plugin and show that it’s not too complicated.
Design
In the beginning, I follow up the strict Figma’s UI but then I decided to change the first screen (my plugin has only two), because It’s the first screen of the plugin, its face and because there is only one button, an additional graphic wouldn’t harm the UX but will help to create the individual plugin's image. Also in my first designs, I used quotes as a logo but then, I thought that the image of Jason from the movie Friday the 13th, his mask would look better in terms of memorability + I could change Jason’s mask depending on the version of the plugin.
The final design and card examples to test the plugin you can find here:
If you want to know more about how to write plugins for Figma there is another good article in 6 parts by Daniel Hollick:
In conclusion
This was the first version of the plugin and the main aim here was to make a proof of concept. During the writing of the plugin, a made several features that are not included here in this version but I will add them in the next version, just need to optimize them better before.
TO-DO
So, in the next plugin version and article I’ll try to:
- show how to use React for Figma plugins
- optimize the current code
- add better feedback messages
- design update.
Any ideas are welcome, so, don’t hesitate to write your suggestions and improvements to my mailbox laptev.graphics@gmail.com or find me on Twitter, Facebook