Penpot Opens Its Design Tool to Plugins
Penpot, the open-source design platform built on web standards, has introduced a plugin system that lets teams extend its capabilities without forking the codebase. The new system follows the project’s broader mission: giving designers and developers a shared, transparent workspace while keeping the tooling flexible enough for custom workflows.
The platform already supports collaborative prototyping, design systems at scale, and generates developer-ready code. It runs in the browser and has gained over 33K stars on GitHub. Its UI is accessible enough for non-designers while matching the output quality of closed-source alternatives like Figma.
Why Open Source Matters Here
For teams that rely on commercial open-source software, the appeal goes beyond cost. The code is auditable, which means quirks and UX gaps can be investigated and addressed directly. Developers often go beyond filing issues; they propose fixes. Self-hosting is another option, offering more privacy, control, or cost savings for teams willing to manage their own infrastructure.
When the maintainers can sustain that model, it’s a win for both the vendor and the users. That’s the context for the plugin system’s arrival.
Building a Plugin
Penpot now hosts a plugin gallery and template library at PenpotHub. If a feature is missing, the intended path is to write a plugin rather than modify the source. Plugins can even be served from localhost during development.
Getting started is straightforward. The project provides templates for several frameworks — one contributed for SolidJS via a pull request. Since plugins are Single-Page Applications, anyone familiar with Vite can build one. Penpot also ships packages to jumpstart development, including CSS loaders and the @penpot/plugin-styles/styles.css import.
The plugin API is exposed on the window object. TypeScript users need to add the provided types to node_modules, then reference them in tsconfig.json under compilerOptions.types. Once that’s wired up, the editor’s language service and the TypeScript compiler understand the penpot namespace, giving auto-completion across the project.
penpot.ui.open("Your Plugin Name", "", {
width: 500,
height: 600
})
A plugin requires a manifest.json in the Vite output directory, specifying where assets live and what permissions the plugin needs.
{
"name": "Your Plugin Name",
"description": "A Super plugin that will win Penpot Plugin Contest",
"code": "/plugin.js",
"icon": "/icon.png",
"permissions": [
"content:read",
"content:write",
"library:read",
"library:write",
"user:read",
"comment:read",
"comment:write",
"allow:downloads"
]
}
Communication between the plugin and the Penpot API works over a bidirectional messaging channel, similar to a Web-Worker setup. Sending a message uses the API’s send methods; receiving responses requires an event listener on the window object at the top level of the plugin scope.
penpot.ui.sendMessage("Hello from my Plugin");
window.addEventListener("message", event => {
console.log("Received from Pendpot::: ", event.data);
})
For more complex plugins with multiple views or routes, cleanup logic is essential to avoid stale listeners. React handles this through effect return statements; SolidJS provides onMount and onCleanup, or the @solid-primitive/event-listener helper for automatic disposal.
Official Guidance and a Contest
The official documentation includes a step-by-step guide covering creation, testing, and publishing. To encourage adoption, Penpot is running a plugin contest from November 15 to December 15. Entries must be fully functional, open-source, and documented — covering features, installation, and usage. Judging criteria include innovation, functionality, usability, performance, and code quality, with a US$ 1,000 first prize.



