Русский
All projects

MonoScript | Figma plugin for routine tasks

My role: Design & Vibecoding · Focus: Figma plugin, DX, Code Editor

How I automated repetitive tasks in my day-to-day design workflow

Try It Out

Feel free to test the prototype above to see how the UI works, or try the fully functional version in Figma.

Open in Figma Community

Why Build This

There’s a whole class of tasks in Figma that usually get solved either manually or using AI via MCP. The AI route requires a paid subscription, while manual labor drains valuable time and cognitive energy that are far better spent on actual system design. Here are a few examples:

Icons

All of these are tedious manual chores, but while reordering takes forever, the first two heavy operations cause Figma to freeze completely.

Components and Variables

Cleaning Up Legacy Files & External Assets

While tools like Scripter exist, they suffer from clunky UX and outdated TypeScript support. So I decided to build my own :)

A Bridge Between LLMs and Figma

The development pipeline works like this:

  1. Prompt an LLM to generate a script (I used Gemini—it excels at rewriting complete code blocks when requesting adjustments).
  2. Paste it into the plugin and hit run.
  3. If it throws an error, click Debug for AI and feed the report back into the model.
  4. Paste the revised code back into the plugin.

The editor is powered by Monaco—the same engine behind VS Code. Anyone familiar with VS Code feels right at home immediately.

Debug for AI

A single click packages everything the LLM needs to fix the script: script name, source code, TypeScript diagnostic errors, runtime exceptions with line numbers and stack traces, and full console output. It formats everything into Markdown and copies it straight to the clipboard.

Чат с моделью
# label

**SCRIPT:**
```typescript
// Labels every selected layer with its own name.
const nodes = figma.currentPage.selection;
console.log("Selection:", nodes.length);

for (const node of nodes) {
  const label = figma.createText();
  label.characters = node.name;
  label.x = node.x;
  label.y = node.y - 24;
  figma.currentPage.appendChild(label);
}

console.log(`Labelled ${nodes.length} nodes`);
```

**ERRORS FOUND:**

- Runtime (line 7:9): **Error** — in set_characters: Cannot write to node with unloaded font "Inter Regular"
  ```
  Error: in set_characters: Cannot write to node with unloaded font "Inter Regular"
      at Object.set [as characters] (<anonymous>)
      at script:s-label.js:7:9
      at eval (<anonymous>)
      at runScript (<anonymous>)
  ```

**CONSOLE OUTPUT (last 30 entries):**
```
[log] Selection: 3
[error] Error: in set_characters: Cannot write to node with unloaded font "Inter Regular"
```
Вставить репорт
# label

**SCRIPT:**
```typescript
// Labels every selected layer with its own name.
const nodes = figma.currentPage.selection;
console.log("Selection:", nodes.length);

for (const node of nodes) {
  const label = figma.createText();
  label.characters = node.name;
  label.x = node.x;
  label.y = node.y - 24;
  figma.currentPage.appendChild(label);
}

console.log(`Labelled ${nodes.length} nodes`);
```

**ERRORS FOUND:**

- Runtime (line 7:9): **Error** — in set_characters: Cannot write to node with unloaded font "Inter Regular"
  ```
  Error: in set_characters: Cannot write to node with unloaded font "Inter Regular"
      at Object.set [as characters] (<anonymous>)
      at script:s-label.js:7:9
      at eval (<anonymous>)
      at runScript (<anonymous>)
  ```

**CONSOLE OUTPUT (last 30 entries):**
```
[log] Selection: 3
[error] Error: in set_characters: Cannot write to node with unloaded font "Inter Regular"
```
The complete workflow: execution, error handling, copying the report to clipboard, and pasting it into the model. Frames represent real UI screenshots, and the report text matches what gets copied to the clipboard.

Non-Blocking Errors

Semantic validation is intentionally disabled. Figma regularly updates its API with new methods that Monaco’s language service might not recognize yet, flagging valid code as an error. In this context, a false positive is far more frustrating than a missed warning, so semantic checks remain silent. Syntax errors stay enabled, as they are actual blockers that prevent script execution.

Craft & Execution

Icons

I used Tabler Icons. Scaling them down from their native 24 px grid to 16 px caused glyph paths to fall off the pixel grid, resulting in blurry renders. Instead of picking a pre-made 16 px icon set, I decided to preserve Tabler’s visual aesthetics and manually redrew the icons on a 16 px grid for crisp rendering on 1080p displays.

Left: Tabler 24 px scaled down to 16—edges fall on subpixels and blur. Right: Redrawn specifically for a 16 px grid.

Folder Morphing

The open and closed folder icons share the exact same vector path command sequence. Instead of swapping graphics, the vector points morph smoothly between states.

Icon manipulations
The same glyph used in the sidebar: enlarged on the left, actual 16 px size on the right.

Empty State

Designed a custom illustration for the zero state when all scripts are deleted.

When the library is completely empty: custom illustration, four core shortcuts, and the primary action button to get started.

Micro-Interactions

Folder expansion states, modal overlays, and context-aware borders that appear when scrolling the sidebar and automatically disappear once scrolled to the top.

Quality Assurance & Verification

I used pixel-diff overlays—layering Figma designs directly over production UI screenshots to catch subtle visual discrepancies that are easy to miss. I then stress-tested the plugin across various edge cases, state combinations, and error scenarios.

Next, I plan to set up an automated audit workflow [specify verification steps here] to minimize the risk of visual regressions or bugs slipping through.

Designing for the Figma Community

Building a personal developer tool vs. releasing a product for thousands of strangers requires a fundamentally different mindset.

What’s Next

Community Script Catalog. A shared repository where users can publish, discover, and vote on community scripts—eliminating the need to write from scratch what someone else has already solved.

Custom Editor Theme. Fully adapting Monaco’s UI to match the MonoScript design system (tooltips, context menus, dropdowns, etc.).

Enhanced Micro-Animations. Refining micro-interactions and transition motion to make the UI feel even more responsive and tactically pleasing.