logo

NJP

Open-Source Meets Design Tooling With Penpot — Smashing Magazine

Articles on Smashing Magazine — For Web Designers And Developers · Nov 14, 0000 · article

This article is a sponsored by [Penpot](https://penpot.app/?utm%5Fsource=Article&utm%5Fmedium=SmashingMag&utm%5Fid=Penpot2.0)

Penpot is a free, open-source design tool that allows true collaboration between designers and developers. Designers can create interactive prototypes and design systems at scale, while developers enjoy ready-to-use code and make their workflow easy and fast because it's built with web technologies, works in the browser, and has already passed [33K starts on GitHub](https://github.com/penpot/penpot).

The UI feels intuitive and makes it easy to get things done, even for someone who’s not a designer (guilty as charged!). You can get things done in the same way and with the same quality as with other more popular and closed-source tools like Figma.

Why Open-Source Is Important

As someone who works with commercial open-source on my day-to-day, I strongly believe in it as a way to be closer to your users and unlock the next level of delivery. Being open-source creates a whole new level of accountability and flexibility for a tool.

Developers are a different breed of user. When we hit a quirk or a gap in the UX, our first instinct is to play detective and figure out why that pattern stuck out as a sore thumb to what we’ve been doing. When the code is open-source, it’s not unusual for us to jump into the source and create an issue with a proposal on how to solve it already. At least, that’s the dream.

On top of that, being open-source allows you and your team to **self-host**, giving you that extra layer of privacy and control, or at least a more cost-effective solution if you have the time and skills to DYI it all.

When the cards are played right, and the team is able to afford the long-term benefits, commercial open-source is a win-win strategy.

Introducing: Penpot Plugin System

Talking about the extensibility of open-source, Penpot has the [PenpotHub](https://penpot.app/penpothub?utm%5Fsource=SmashingMag&utm%5Fmedium=Article&utm%5Fcampaign=PluginsContest) the home for open-source **templates** and the newly released **plugin** gallery. So now, if there’s a functionality missing, you don’t need to jump into the code-base straightaway — you can create a plugin to achieve what you need. And you can even serve it from localhost!

### Creating Penpot Plugins

When it comes to the plugins, creating one is extremely ergonomic. First, there are already set [templates](https://penpot.app/penpothub/libraries-templates?utm%5Fsource=SmashingMag&utm%5Fmedium=Article&utm%5Fcampaign=PluginsContest) for a few frameworks, and I created one for [SolidJS in this PR](https://github.com/penpot/plugin-examples/pull/2) — the power of open-source!

When using [Vite](https://vite.dev/), plugins are Single-Page Applications; if you have ever built a Hello World app with Vite, you have what it takes to create a plugin. On top of that, the Penpot team has a few packages that can give you a headstart in the process:

```
npm install @penpot/plugin-styles

```

That will allow you to import with a CSS loader or a CSS import from `@penpot/plugin-styles/styles.css`. The JavaScript API is available through the window object, but if your plugin is in TypeScript, you need to teach it:

```
npm add -D @penpot/plugin-types

```

With those types in your `node_modules`, you can pop-up the `tsconfig.json` and add the `types` to the `compilerOptions`.

```
{
"compilerOptions": {
"types": ["@penpot/plugin-types"]
}
}

```

And there you are, now, the Language Service Provider in your editor and the TypeScript Compiler will accept that penpot is a valid namespace, and you’ll have auto-completion for the Penpot APIs throughout your entire project. For example, defining your plugin will look like the following:

```
penpot.ui.open("Your Plugin Name", "", {
width: 500,
height: 600
})

```

The last step is to define a plugin manifest in a `manifest.json` file and make sure it’s in the outpot directory from Vite. The manifest will indicate where each asset is and what permissions your plugin requires to work:

```
{
"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"
]
}

```

Once the initial setup is done, the communication between the Penpot API and the plugin interface is done with a bidirectional messaging system, not so different than what you’d do with a Web-Worker.

So, to send a message from your plugin to the Penpot API, you can do the following:

```
penpot.ui.sendMessage("Hello from my Plugin");

```

And to receive it back, you need to add an event listener to the `window` object (the top-level scope) of your plugin:

```
window.addEventListener("message", event => {
console.log("Received from Pendpot::: ", event.data);
})

```

**A quick performance tip**: _If you’re creating a more complex plugin with different views and perhaps even routes, you need to have a cleanup logic. Most frameworks provide decent ergonomics to do that; for example, React does it via their return statements._

```
useEffect(() => {
function handleMessage(e) {
console.log("Received from Pendpot::: ", event.data);
}
window.addEventListener('message', handleMessage);

return () => window.removeEventListener('message', handleMessage);
}, []);

```

And Solid has `onMount` and `onCleanup` helpers for it:

```
onMount(() => {
function handleMessage(e) {
console.log("Received from Penpot::: ", event.data);
}
window.addEventListener('message', handleMessage);
})

onCleanup(() => {
window.removeEventListener('message', handleMessage);
})

```

Or with the [@solid-primitive/event-listener](https://primitives.solidjs.community/package/event-listener#createeventlistener) helper library, so it will be automatically disposed:

```
import { makeEventListener } from "@solid-primitives/event-listener";

function Component() {

const clear = makeEventListener(window, "message", handleMessage);

// ...
return (Hello!)
}

```

In the official documentation, there’s a [step-by-step guide](https://help.penpot.app/plugins/create-a-plugin?utm%5Fsource=SmashingMag&utm%5Fmedium=Article&utm%5Fcampaign=PluginsContest) that will walk you through the process of creating, testing, and publishing your plugin. It will even help you out.

So, what are you waiting for?

Plugin Contest: Imagine, Build, Win

Well, maybe you’re waiting for a push of motivation. The [Penpot](https://penpot.app/?utm%5Fsource=SmashingMag&utm%5Fmedium=Article&utm%5Fcampaign=PluginsContest) team thought of that, which is why they’re starting a [Plugin Contest](https://penpot.app/plugins-contest?utm%5Fsource=SmashingMag&utm%5Fmedium=Article&utm%5Fcampaign=PluginsContest)!

For this contest, they want a fully functional plugin; it must be open-source and include comprehensive documentation. Detailing its features, installation, and usage. The first prize is US$ 1000, and the criteria are innovation, functionality, usability, performance, and code quality. The contest will run from November 15th to December 15th.

Final Thoughts

If you decide to build a plugin, I’d love to know what you’re building and what stack you chose. Please let me know in the comments below or on [BlueSky](https://atila.io/bsky)!

View original source

https://smashingmagazine.com/2024/11/open-source-meets-design-tooling-penpot/