🎁 Get the FREE AI Skills Starter GuideSubscribe →
BytesAgainBytesAgain
🦀 ClawHub

Figma Plugin Writer

by @zerozlw

自动生成和更新 Figma 插件的 code.js 以创建和修改设计元素,用户更新代码后需手动运行插件执行。

Versionv1.0.0
Downloads874
TERMINAL
clawhub install figma-plugin-writer

📖 About This Skill


name: figma-plugin-writer description: Write Figma plugin code to automate UI design in Figma files. Activate when user wants to create UI mockups, design systems, app screens, or visual prototypes directly in Figma via plugin code. NOT for: Figma API REST calls, file management, or commenting.

Figma Plugin Writer

Write plugin code (code.js) to automate design in Figma files. After updating the code, notify the user to run the plugin.

Prerequisites

The user must provide: 1. Plugin directory — folder containing code.js and manifest.json 2. Code file — typically code.js 3. Target Figma file — optional, for context

Workflow

1. Receive design requirements from the user 2. Write plugin code to code.js 3. Notify user: Plugins → Development → 4. Iterate based on feedback

API Reference

Font Loading (required before creating text)

await figma.loadFontAsync({ family: "Inter", style: "Regular" });
await figma.loadFontAsync({ family: "Inter", style: "Medium" });
await figma.loadFontAsync({ family: "Inter", style: "Semi Bold" });
await figma.loadFontAsync({ family: "Inter", style: "Bold" });

Frame (Container)

var frame = figma.createFrame();
frame.name = "MyFrame";
frame.resize(width, height);
frame.cornerRadius = 12;
frame.fills = [{ type: "SOLID", color: { r: 1, g: 1, b: 1 } }];
frame.x = 0;
frame.y = 0;

Text

var text = figma.createText();
text.characters = "Hello World";
text.fontSize = 16;
text.fontName = { family: "Inter", style: "Regular" };
text.fills = [{ type: "SOLID", color: { r: 0, g: 0, b: 0 } }];

Rectangle

var rect = figma.createRectangle();
rect.resize(100, 50);
rect.fills = [{ type: "SOLID", color: { r: 0.9, g: 0.2, b: 0.2 } }];
rect.cornerRadius = 8;

Nesting Nodes

frame.appendChild(text);
parentPage.appendChild(frame);

Drop Shadow

frame.effects = [{
  type: "DROP_SHADOW",
  color: { r: 0, g: 0, b: 0, a: 0.1 },
  offset: { x: 0, y: 4 },
  radius: 12,
  spread: 0,
  visible: true,
  blendMode: "NORMAL",
}];

Stroke

frame.strokes = [{ type: "SOLID", color: { r: 0.8, g: 0.8, b: 0.8 } }];
frame.strokeWeight = 1;

Text Alignment

text.textAlignHorizontal = "CENTER"; // LEFT | CENTER | RIGHT | JUSTIFIED
text.textAlignVertical = "CENTER";   // TOP | CENTER | BOTTOM

Auto Layout (inside Frame)

frame.layoutMode = "VERTICAL"; // or "HORIZONTAL"
frame.primaryAxisAlignItems = "CENTER";   // MIN | CENTER | MAX | SPACE_BETWEEN
frame.counterAxisAlignItems = "CENTER";
frame.paddingTop = 16;
frame.paddingBottom = 16;
frame.paddingLeft = 16;
frame.paddingRight = 16;
frame.itemSpacing = 8;

Page Navigation

var pages = figma.root.children;
var targetPage = pages[pages.length - 1];
await figma.setCurrentPageAsync(targetPage);

Clear Page Content

var old = targetPage.children.slice();
for (var i = 0; i < old.length; i++) {
  old[i].remove();
}

Viewport

figma.viewport.scrollAndZoomIntoView([frame]);

Notifications

figma.notify("Done!", { timeout: 3000 });
figma.notify("ERROR: " + e.message, { timeout: 10000 });

Page Info

var pages = figma.root.children;
var count = pages.length;
var pageName = pages[0].name;

Code Template

async function main() {
  try {
    // 1. Load fonts
    await figma.loadFontAsync({ family: "Inter", style: "Regular" });
    await figma.loadFontAsync({ family: "Inter", style: "Bold" });

// 2. Get target page var pages = figma.root.children; var target = pages[pages.length - 1]; await figma.setCurrentPageAsync(target);

// 3. Clear old content var old = target.children.slice(); for (var i = 0; i < old.length; i++) old[i].remove();

// 4. Create design... var frame = figma.createFrame(); frame.name = "Screen"; frame.resize(375, 812); frame.fills = [{ type: "SOLID", color: { r: 1, g: 1, b: 1 } }]; frame.x = 0; frame.y = 0; target.appendChild(frame);

// 5. Done figma.viewport.scrollAndZoomIntoView([frame]); figma.notify("Design complete!", { timeout: 3000 });

} catch (e) { figma.notify("ERROR: " + e.message, { timeout: 10000 }); } }

main();

Pitfalls & Gotchas

documentAccess: "dynamic-page" Mode

If manifest.json has "documentAccess": "dynamic-page":

  • figma.currentPage = page → ✅ await figma.setCurrentPageAsync(page)
  • figma.getNodeById() → ✅ await figma.getNodeByIdAsync()
  • figma.closePlugin() → ✅ await figma.closePluginAsync()
  • Error Handling

  • Always wrap code in try-catch
  • Show errors via figma.notify("ERROR: " + e.message, { timeout: 10000 })
  • Do not use emoji in text content (font may not support the glyph)
  • Do not call figma.closePlugin() automatically (let user close manually)
  • Free Tier Limits

  • Max 3 Pages — do not create new Pages
  • Work within existing Pages (clear and rebuild)
  • Fonts

  • Default: Inter (built into Figma)
  • Supported styles: "Regular", "Medium", "Semi Bold", "Bold"
  • Colors use { r, g, b } format with 0-1 range
  • Iteration Pattern

    On each design iteration: 1. Clear old elements: page.children.slice().forEach(c => c.remove()) 2. Recreate design with changes 3. Notify user to re-run the plugin

    ⚙️ Configuration

    The user must provide: 1. Plugin directory — folder containing code.js and manifest.json 2. Code file — typically code.js 3. Target Figma file — optional, for context