✨ Add an icon to the MCP browser extension

Give the extension the Penpot logo, white on a black rounded square, so
it reads on light and dark toolbars. The SVG source sits next to PNGs
at 16, 32, 48 and 128 px, which both manifests list as the extension
icons and the toolbar button icon. The README explains how to redraw
the PNGs from the SVG.
This commit is contained in:
alonso.torres 2026-10-26 10:32:45 +00:00
parent c13fb65e99
commit 9a21873e24
8 changed files with 44 additions and 1 deletions

View File

@ -17,6 +17,15 @@ for the plugin to answer again, and then runs the task.
The popup turns waking on or off and lists the paired sessions and server connections.
The icon is the Penpot logo; `public/icons/icon.svg` is its source. To redraw the PNGs after
changing it:
```sh
for size in 16 32 48 128; do
rsvg-convert -w $size -h $size public/icons/icon.svg -o public/icons/icon-$size.png
done
```
## How a tab is woken
- **Chrome** unfreezes the page in place: the extension attaches the debugger to the tab,

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 472 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128">
<rect width="128" height="128" rx="28" fill="#000000" />
<svg x="12" y="12" width="104" height="104" viewBox="-42 0 346 346">
<path fill="#ffffff" transform="translate(136.64258,-280.3457)" d="m -68.324219,280.3457 -36.376951,51.23633 0,28.96289 -31.65625,15.05664 -0.28516,-0.13476 0,11.90234 0,177.05078 123.417971,58.30664 7.5429684,3.56055 7.5410156,-3.56055 123.419925,-58.30664 0,-188.95312 -0.23242,0.10937 -31.666021,-15.06055 0,-28.93359 -1.107421,-1.55859 -35.271485,-49.67774 -36.378906,51.23633 0,0.0508 -26.4707032,-37.28125 -26.2656248,36.99414 -0.939453,-1.32226 -35.271485,-49.67774 z m 6.435547,29.76172 14.070313,19.81641 -41.011719,0 13.90625,-19.58399 13.035156,-0.23242 z m 125.326172,0 14.070312,19.81641 -41.011718,0 13.904297,-19.58399 13.037109,-0.23242 z m -62.84960938,14.00781 14.07031238,19.81446 -41.009765,0 13.904296,-19.58399 13.03515662,-0.23047 z m -93.30664062,15.79493 19.451172,0 0,65.49609 -19.451172,-9.18945 0,-56.30664 z m 29.4375,0 19.353516,0 -0.002,79.35546 -19.353515,-9.14257 0.002,-70.21289 z m 95.886719,0 19.453125,0 -0.002,70.14648 -19.449219,9.1875 -0.002,-79.33398 z m 29.4375,0 19.353515,0 0,56.28515 -19.353515,9.14258 0,-65.42773 z m -92.285157,14.00586 19.451172,0 0,81.0039 -19.451172,-9.18945 0,-71.81445 z m 29.4375005,0 19.3535155,0 -0.002,71.9707 -19.35351562,9.14453 0.001953,-81.11523 z m 94.1835935,21.52539 17.125004,7.00195 -17.125004,8.08984 0,-15.09179 z m -198.080076,0.0254 0,15.08984 -17.12305,-8.08984 17.12305,-7 z m -16.85938,23.80859 108.335941,51.17773 0,155.58985 -108.335941,-51.17774 0,-155.58984 z m 231.75586,0 0,155.58984 -108.335935,51.17774 0,-155.58985 108.335935,-51.17773 z"/>
</svg>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -1,6 +1,13 @@
/** Browsers the extension is built for, one directory of `dist/` each. */
export const BROWSERS = ["chrome", "firefox"];
const ICONS = {
16: "icons/icon-16.png",
32: "icons/icon-32.png",
48: "icons/icon-48.png",
128: "icons/icon-128.png",
};
const CONTENT_SCRIPTS = [
{
matches: ["https://design.penpot.app/*", "https://localhost/*", "http://localhost/*"],
@ -23,9 +30,11 @@ export function createManifest(browser) {
name: "Penpot MCP Wake",
version: "0.1.0",
description: "Wakes a background Penpot tab when an MCP task needs it.",
icons: ICONS,
action: {
default_title: "Penpot MCP Wake",
default_popup: "popup.html",
default_icon: { 16: ICONS[16], 32: ICONS[32] },
},
content_scripts: CONTENT_SCRIPTS,
};

View File

@ -1,4 +1,5 @@
import assert from "node:assert/strict";
import { access } from "node:fs/promises";
import test from "node:test";
import { BROWSERS, createManifest } from "../scripts/manifest.mjs";
@ -56,6 +57,24 @@ test("runs the content script on Penpot and on local development instances", ()
test("opens the popup from the toolbar button", () => {
for (const manifest of [chrome, firefox]) {
assert.deepEqual(manifest.action, { default_title: "Penpot MCP Wake", default_popup: "popup.html" });
assert.deepEqual(manifest.action, {
default_title: "Penpot MCP Wake",
default_popup: "popup.html",
default_icon: { 16: "icons/icon-16.png", 32: "icons/icon-32.png" },
});
}
});
test("has icons for the toolbar, the extensions page and the stores, all in public/", async () => {
for (const manifest of [chrome, firefox]) {
assert.deepEqual(manifest.icons, {
16: "icons/icon-16.png",
32: "icons/icon-32.png",
48: "icons/icon-48.png",
128: "icons/icon-128.png",
});
for (const path of Object.values(manifest.icons as Record<string, string>)) {
await access(new URL(`../public/${path}`, import.meta.url));
}
}
});