This article is about my experience building a Figma plugin. Making the plugin was surprisingly easy and rich with creative potential. This article is also an opportunity for me to share my thoughts on the importance of extensible software, and what it means for software to be dynamic
and user defined
. Although I find extensibility - it’s importance, and how to achieve it - a fascinating subject, I discovered that I need to do a lot more research before I can effectively describe my own experiences with this dimension of software.
Repo
But I do know that Figma fits into this experience. When I first used Figma (Design), I was surprised at how intuitive it was to learn. Later, when opening up Figma’s whiteboarding program, FigJam, I was amazed at how fun it was. I would urge my colleagues to hop into a whiteboard with me, and I would look forward to presenting my cloud architecture suggestions.
As someone who has been drawing my whole life, I felt at home on a blank expanse of canvas in a way I never had in digital “document”. On a more social level, it was also really interesting to see people interact in 3D space, and watch my colleagues play around with shapes in real time. It was the closest I’ve gotten to playing videogames at work. By playing the exception, it has also served as a sort of reminder of how much computers often isolate us.
Allegory
There was a time in college when I carried a small, thin notebook everywhere. I would doodle in it to pass the time, and I would use to create my todos for the the day, referencing it frequently when I was waiting in line, or had a few spare moments. Sometimes referencing todos turned into a more reflective process, where I would write out details for an art project, or things I wanted to tell a friend.
What I found was that people would stop and ask me what I was doing all the time. In line for food, on benches, in public transit. It was constant. People seemed to be both interested enough and unconcerned enough about crossing any sort of assumed privacy boundary that they would start up conversations all the time.
And I loved it. It was very refreshing. Especially because I would often enjoy sharing these short snippets of my life, my day, and my psyche. I rarely wrote anything too personal in those notebook - more tasks and ideas.
It was so obvious to contrast this to writing notes in a phone that I quickly realized that this never happened when using a phone to do the exact same thing.
I’ve used FigJam in particular for a wide range of personal projects, including:
Planning a Canoeing trip
Visualizing Binary Trees
Creating product roadmaps
Laying out the electrical system, layout, and build process for my camper van conversion.
Note
I haven’t blogged about my camper van conversation yet, but I plan to.
So I can attest to the power of the base features of Figma as a way to fluidly explore ideas. Like many modern applications, Figma can be extended with plugins. In order to be available from within the app, each plugin most go through a review process. But they can still be developed locally without that being necessary.
My colleague Seth Walker told me that he was building a Figma plugin, I was interested what that process would be like. I have built a very simple Chrome Extensionbefore, as well as an Obsidian Plugin, and in both cases I felt that the development experience taught me a lot about the internal workings of the parent software. In a very real way, plugins allow users to participate in the building process of software. Because I appreciate Figma software, I was curious how it worked.
On Figma Plugins, and Plugins in General
I want to provide a quick primer to Figma plugins if you haven’t seen them. Here’s a video of me exploring a couple out of the 3000 plugins available:
Ultimately, I think that many of the plugins that exist in Figma are too niche, or marketing ploys or experiments, or are too silly to really be useful. I’m not sure why this is. But despite this, the potential availability of the perfect plugin is reassuring, and tends to make me trust Figma more because it means the creators are invested in extensibility.
I read an article the other day about Dynamic Documents as Personal Softwarethat described how software is often rigid, designed to do a single purpose. I feel the writers captured a very important truth when they wrote:
“How might we reorient computing so that people can deeply tailor software to meet their unique needs?”
Inkandswitch.com
The authors of this article contrast the idea and rigidity of a note-taking app as an example of the app
in general with the flexibility of a paper note.
One humble but ubiquitous vision of what flexibility in software looks like is the settings
panel:
Settings panel in Obsidian
But the configurations available in an app’s settings are rarely foundational to the functionality of the app itself.
Users of the settings
panel are beholden to a discrete and limited set of options exposed to them by a developer. That’s why I tend to think of applications with a plugin ecosystem as having a fundamentally different ethos than those without. I trust their approach more.
This is far from a complete reflection on the dichotomy between dynamic
and static
programs, because this vocabulary is new to me. I think the distinction is exciting, and provides language for experiences I’ve had using different tools that inspired me as a developer (whether it was by way of frustration, or delight).
Figma has provided some of the tools that made me subtly rethink what was possible in software, which is why I’m thinking about these things.
Creating a Figma Plugin
Here is the sample code Figma provided Seth and I with when we got started:
I appreciate the comments that are included.
You can easily generate this code and get started by following the quickstart guide, which essentially tells you to right click in Design or FigJam and select Plugins > Development > New Plugin
.
Figma recommends you build in typescript, just because you interact with many Figma types. Make sure you build your typescript into javascript, and then run your plugin by selecting it in the development
menu we just used. If it was the last one run, you can also use the hotkey option + command + p
(on mac) to run it again without having to navigate through the menu.
Figma plugins don’t need to have UI, and can execute javascript once upon initiation, but I want to be able to listen for key events and send them to our running javascript process, for which I need to have an html
file called ui.html
:
The Goal
After helping my colleague build Conway’s Game of Life in Figma, I thought “huh, Figma is sort of like a game engine”, probably because many of my programming and design challenges have come from making games. My first thought was whether I could create a “character” that could be moved around the screen with the WASD keys.
I cannibalized Seth’s code, grabbed a rectangle creation line, subscribed to some keypress event listeners, and got that rectangle moving around the screen using user input.
In order to do that I needed some HTML - it’s possible to create Figma plugins that only execute Javascript, but after reading the documentation, it looked like I could only listen to key events through a special file called ui.html
rather than the javascript file listed in the plugin manifest. Here it is:
All we’re really doing here is creating a start button, focusing on the document body, and listening for a certain subset of key input events that we post to the window.
After writing the code to move this rectangle around like a sort of 2D cursor
, I had an urge to interact with the surrounding FigJam environment, so I added the ability to “paint” boxes of the same kind around the box using the UHJK keys, sort of like WASD, but a directional box creation mechanism.
This was cool, and I could recycle the same createRectangle
I used to make the cursor
rectangle, but it was awkward to paint around the rectangle, so I added the ability to paint at the location of the rectangle.
Then I noticed that the cursor
’s z-index was less than the boxes it created, and it got lost behind them. I found no way to directly manipulate z-index in the API reference material, so I rewrote the way I moved my box so that I instead deleted and recreated it for the illusion of movement, making use of how newer objects in Figma are placed one top of older objects. This is the code I ended up with:
Then I added undo! Previously, it was only possibly to undo all of the new squares at once.
I also made sure that the cursor
square was removed when the plugin was closed.
Lastly, it was boring to just have one color, so I also added the ability to cycle through colors using the number keys 3-8
(so the right hand could easily use them, instead of the left, which is busy with the WASD
keys). I grabbed the colors out of this photo of me and my brother I really like taken after I almost drowned in the ocean:
Here’s a video of me playing around with it on top of the photo the colors are based on:
And here’s a little dude I made:
This is the process of making said lil’ dude:
I made some…other creatures too. Sorry, I misplaced one of their noggins:
It turns out that one awesome thing about making pixel art in Figma is that because the result is a set of RectangleNoes, which can be copied, deleted, rotated and manipulated post-creation in all the same ways objects can normally be manipulated in Figma. They be exported as a PNG simply by using the command + shift + c
hotkey.
Or as JPGs using the menu or command + shift + e
export hotkey.
The repo is public, so please feel free to clone/fork it and use it in figma
I don’t have time to go through the Figma publishing process right now, but if you find it useful (or don’t!), please let me know. I welcome all feedback.
What’s next for this project
Implement undo- When the box zooms out of the screen, focus the view on the box. I know this is very doable because the example plugin Figma provides does this
- I found this problem actually a bit tricky to define, and that using the mouse to readjust the view might be a better solution than manually readjusting the view. HOWEVER, I did comment out a line that used a list of the entire history of the plugin to readjust the view, which actually work pretty well, depending on what you are doing.
- ~~Make sure the moving box that is used like a sort of cursor has a higher z-index than the boxes it makes, so it never gets lost underneath those boxes.
Actually getting the boxes to stack along the same grid every time (I tried to do this with the snapCoords method, but it isn’t quite behaving)Immediately after writing this I realized that the snap to coords method was not snapping to the full width of the box.- Test out multiplayer
- Floodfill?
- Allow the cursor to ‘eyedrop-tool’ the color below it (looked into this and there is no obvious way to do this I could find on first glance)
- Make a multiplayer game.
Reflections
I am reaching for a way to categorize the flexibility of different programs, and I’m struggling to quantify this is a satisfying way. Turns out it’s difficult to categorize software on just two dimensions, but here’s an attempt to show how software with plugin / extension ecosystems stacks against other things. I will leave you with this diagram I made in an attempt to map these dimensions out: