Integrating Figma with Fever to speed-up the Product Design

Pablo Díez
Fever Engineering
Published in
8 min readNov 16, 2022

--

Image from figma.com

At Fever, we are always searching for new ways to improve the user experience, taking into account that needs are very different in a Harry Potter Exhibition than for a Music and gastronomic event where seating selection is a must. To achieve this, Our engineering product Design team is always finding ways to adapt their tools so that they work well in every scenario. The most recent example of this is Figma, a powerful tool that has greatly improved the work process for our Product Designers.

The constant problem the team was facing with previous design tools was providing content from our platform (images, titles, descriptions…) and integrating it in the design files easily.

Before Figma, they had to manually download and copy updated content from our systems, and then proceed to upload it and use it for each tool and design. It was an extenuating task; Product Designers shouldn’t be spending their time one this.

What solution did we come up with?

We’ve created a Figma Plugin that helps extract contents from the system, display and loads and displays it easily in the Figma files.

Want to make your day-to-day easier as well? Keep on reading, we will walk you through the steps of creating a simple and awesome Figma plugin that fetches and links text and images directly in the Figma file.

Architecture

Let’s start with the basics: understanding how a Figma plugins work. Basically, there are two parts: scene and ui:

Scene

This is the part of the application that will be executed in a sandbox environment of the Figma app or website, providing us a way to access the layers of the Figma document. In this environment we won’t have access to the browser APIs so we will have to take this into account when writing the related code in this part.

UI

Opposite to the Scene, in this part of the application we will have access to the Browser APIs but not to the Figma API because the code will be executed in a regular iframe.

Figma Plugin architecture from the official documentation

To communicate between both layers we will use the postMessage API. The message will be serialized so any function in the serialized object will be lost.

Tools

To get started, download the Figma desktop app for Mac or Windows here. You will need it later to test your plugin.

Scaffolding

Creating the Manifest file

The manifest.json file defines the plugin.

The main property will define the entry point to be executed in the sandbox environment and the ui property the one to be executed when calling the showUI method (iframe).

The id property will define the plugin ID for publishing. Right now, it is not important as we will just be developing the plugin and loading it in the Figma app for testing.

All properties are described here.

Start a NPM project

To manage the dependencies, as usual, use NPM. Start a project using npm init or just create a package.json in the root folder with the following content:

There are several dependencies that will be used in following steps so just keep reading!

Setting up Webpack

Well, now we have the plugin and the dependencies defined but we want to manage our code easily. For this, we are going to add a Webpack configuration to build the plugin and start a development environment. You could use any other similar tool like Rollup or Vite if you want.

The Figma team provides us an example configuration using Webpack and React so we are going to use it and improve some parts:

The first important change is adding capabilities to process SCSS/SASS files adding the sass-loader and updating the file extension in the rules block:

{
test: /\.s[ac]ss$/i,
use: [
'style-loader',
'css-loader',
'sass-loader',
],
}

We also added a way to load environment variables using dotenv and the already configured DefinePlugin just passing the loaded configuration.

new webpack.DefinePlugin(getEnvVars())

Finally, a small change that will help while developing the plugin is to set the cache property to false in the HtmlWebpackPlugin configuration to avoid problems when using watch with Webpack.

Configuring Typescript

Just create a tsconfig.json file in the root folder with the following content so Webpack will use it to transform the TS files:

The contents

Now it is time to write some application code: create an example database, fetch the data, and display it in the UI side of the plugin. We will use React as our main UI library but you could use any other library or framework if you want.

Creating an example API

A fast way to create an example database is using json-server service.

If you want to skip this part, you could use the database from this article: https://my-json-server.typicode.com/wishrd/awesome-figma-plugin/events.

Create a public Github repository (or use the same that you have for the plugin if it is public) with a db.json file in the root that has this content:

After pushing the changes to the repository, you will have access to the API through https://my-json-server.typicode.com/<username>/<repository_name>/events

Displaying the events

We are going to create some files to display our Figma plugin:

Folder structure

Create a folder called src and two subfolders: controller and ui that will separate the code of each layer (scene and ui).

Create an index.ts file under the controller folder and display the UI using the figma API:

figma.showUI(__html__);

The __html__ variable will reference the ui property of the manifest.json.

Now, in the ui folder, create a basic React app with two pages: Home and Detail.

Create the src/index.html and src/index.tsx files to bootstrap the app.

index.html

<div id="root"></div>

Due to the way of the UI loads, the standard router won’t work but routes still are able to be used through the MemoryRouter.

Create the Home and Detail pages under src/ui/app:

Right now, we have two basic pages waiting for us to fill the events and event variables. For this, we will connect with our database API using an effect and the fetch API. But first, we need to configure our API_BASE url through the .env file.

Create an .env file the root folder:

API_BASE=https://my-json-server.typicode.com/<username>/<repository_name>

Create an index.ts file under src/ui/env to get a typed object:

declare var API_BASE: string;

export const Env = {
API_BASE: API_BASE
};

You could add any other environment variable that you need in this file to make it accessible through the Env constant.

Now we are ready to make the requests to the database API.

Add the effect to the Home.tsx:

And to the Detail.tsx:

At this point you should have something like this:

Home page
Detail page

Ey, wait, how are we displaying this?

  1. Download and open the desktop Figma app if you didn’t do it yet.
  2. Start the project with npm start command.
  3. Click on Import plugin from manifest under Plugins > Development and open it with right click > Plugins > Development > Awesome Plugin:

The UI looks pretty bad, so we are going to add some basic styles at least:

First, in the controller.ts, increase the size of the plugin viewport passing this option object to the showUI method

figma.showUI(__html__, { width: 360, height: 400 });

Create the file src/ui/styles/styles.scss and import it on index.tsx:

Create the file src/ui/app/Home.scss and import it on Home.tsx:

Create the file src/ui/app/Detail.scss and import it on Detail.tsx:

Updating Figma document elements

Finally, we are going to interact with the Scene of the Figma files. The communication between layers is done using the postMessage API as we’ve described above.

Figma pages work with nodes. So the goal is to load the image in a FillableNode and the text in a TextNode.

In the Detail.tsx, add two callbacks, one per action type:

And create the helper to transform the image into bytes. Remember that we have Network access only in the UI layer, so one way to transform the image is to download the image into a canvas element and get the bytes from the canvas context:

Something important when sending events from the UI is to wrap the message into the pluginMessage object.

Use the callbacks with the onClick property on the related HTML elements:

Now we are sending events to the Scene, but we need to capture them and use them to... For this, we have to listen to the onmessage property of figma.ui API. Add the following lines to the controller/index.ts:

Lets add a small util src/controller/utils to get the current selected node first and dive into the setNodeText and setNodeImages:

The setNodeText will get the node and check if the node type is TEXT. Also, the node must have a font defined. Why? to load the text properly it is required to load the font first. This can be done with the Figma API method loadFontAsync:

As you can see, loading text into a node of type TEXT is easy.

To load an image we must create the setNodeImage helper that will be a bit complex compared with the setNodeText helper.

First, let’s create the FillableNode type as a union of node types with fills property:

Then use this type and helper to filter the allowed nodes in the setNodeImage helper.

Now lets set the image into any of these nodes:

  1. Create the image using figma.createImage method.
  2. Find the fills item of type IMAGE if it exists.
  3. Set the image: replace the fills item imageHash with the new image or just push a new fill item of type IMAGE if there is no one previously.

Awesome! Now you have your first Figma plugin working and it should looks and works like this:

This is just a small example about something similar to what we’ve done in Fever for helping our Product Designers. Here is the link to the full example:

Of course, you should take into consideration the following points to achieve an scalable and enterprise plugin:

  • Publish the plugin in private mode.
  • Protect the access to your API in some way (VPN, login…).
  • Think about the architecture of both parts: UI and Controller (Scene). You could use scoped styles, state management libraries, event bus… there are a lot of strategies to design a scalable architecture.
  • Use any library/framework that fits your requirements for the UI: Angular, Svelte, React, Vue… there is no limitation here.

Conclusion

With the Figma plugin, we have managed to stop spending so much time on repetitive tasks, increasing productivity and having more time to focus on what really matters to us: designing a quality product for our users.

If you found this article useful and interesting and would like to work, find out more about the engineering department and the available jobs on this link.

--

--