how-to-build-a-plugin-system-on-the-web-and-also-sleep-well-at-night

At Figma, we recently tackled one of our biggest engineering challenges yet: supporting plugins. Our plugins API enables third-party developers to run code directly inside our browser-based design tool, so teams can adapt Figma to their own workflows. They can enable accessibility checkers to measure contrast, translation apps to convert language, importers to populate designs with content, and anything else their heart desires.

We knew we needed to design this plugin functionality carefully. Throughout the history of software, there have been many instances where third-party extensions negatively affected a platform. In some cases, they slowed the tool to a crawl. In other cases, the plugins broke whenever new versions of the platform were released. To the extent that we could control it, we wanted users to have a better plugin experience with Figma.

Furthermore, we wanted to make sure plugins would be safe for users to run, so we knew we wouldn’t want to simply eval(PLUGIN_CODE). That is the quintessential definition of insecure! Yet, eval is essentially what running a plugin boils down to.

To add to the challenge, Figma is built on a very unconventional stack with constraints that previous tools haven’t had. Our design editor is powered by WebGL and WebAssembly, with some of the user interface implemented in Typescript & React. Multiple people can be editing a file at the same time. We are powered by browser technologies, but also limited by them.

This blog post will walk you through our pursuit for the perfect plugin solution. Ultimately, our efforts boiled down to one question: How do you run plugins with security, stability, and performance? Here’s a brief overview of our many non-trivial constraints:

Security: Plugins only have access to the file when explicitly launched. Plugins are restricted to the current file. Plugins can’t make calls as figma.com. Plugins can’t access each other’s data unless given willingly. Plugins can’t tamper with the Figma UI and behavior to mislead the user (e.g. phishing).
Stability: Plugins should not be able to slow down Figma as to make it unusable. Plugins should not be able to break key invariants in our product, such as the property that everyone always sees the same thing when viewing the same file. It should not be necessary to manage plugin installation across devices/users in order to view a file. Changes to the Figma product or internal APIs should rarely, if ever, break existing plugins.
Ease of development: Plugins should be easy enough to develop to support a vibrant ecosystem. Most of our users are designers, and may only have moderate experience with JavaScript. Developers should be able to use existing debugging tools.
Performance: Plugins should run fast enough to support most common use cases, such as searching the document for a layer, generating charts, etc.

We considered dozens of different approaches branching into all sorts of different paths. We had weeks of discussing, prototyping and brainstorming. This blog post will focus on just three of those attempts that formed the most central path in our exploration.

For me, it has been the most satisfying exercise in first principles thinking. I had fun leveraging all the computer science fundamentals I learned in the classroom (the ones I never thought I’d ever use in the real world). If that idea excites you too, we’re hiring!

Attempt #1: The