Figma Plugin

Figma Plugin

Vibecoding

Vibecoding

Productivity

Productivity

I Wondered If I Could Vibecode a Copywriting Plugin. Now My Team Uses It Daily.




I Wondered If I Could Vibecode a Copywriting Plugin. Now My Team Uses It Daily.

April 2nd, 2026

April 2nd, 2026

How I went from zero plugin experience to shipping a tool my team relies on daily.

How I went from zero plugin experience to shipping a tool my team relies on daily.

The problem hiding in plain sight.

The problem
hiding in plain sight.

My company recently put together a set of copywriting rules and principles for our product. To help designers follow them, we built a custom GPT trained on those guidelines. The idea was simple: paste a screenshot of your UI, and the GPT suggests copy that matches our brand voice.


On paper, solid solution. In practice, it created a different kind of problem.


I started watching how designers on my team actually used it day to day, and I noticed two problems:

The constant back and forth.

Designers kept switching between Figma and ChatGPT over and over. Screenshot the UI, put it in GPT, get a recommendation, choose the final copy, put it back into the UI. If it's just one or two screens, it's fine. But I noticed they were relying on it for most of their screens. That's a lot of context-switching eating into their focus time.

The suggestions were hard to map.

When you send a screenshot to GPT, the suggestions come back as one long block of text and it's hard to tell which copy belongs to which part of the UI. Since you're constantly going back and forth between the two tools, it never really feels efficient.

Each of these feels minor on its own. But added up across a full workday, the friction was significant.

That's when I started to question: what if this entire workflow could happen inside Figma itself?

Deciding to build something

I didn't know how to build

Deciding to build something

I didn't know how to build

I'd never touched the Figma Plugin API, so I was starting from absolute zero.


But two things came together at the right time. I'd been wanting to explore Claude Code as a creative tool for designers, and I had a real problem in front of me that was affecting my team's daily work. That felt like the right moment to experiment.


I started by asking ChatGPT about technical feasibility. It recommended a phased approach: build the plugin UI first, then implement text extraction from Figma layers, then connect to an LLM. Reasonable and methodical.

Getting ChatGPT’s suggestion about technical feasibility

Getting ChatGPT’s suggestion about technical feasibility

But I was curious about a different question. If I gave an AI the full context of what I was trying to build, how much could it do on its own?


So I gave Claude Code the same brief and told it to build the whole thing at once.

Claude’s first attempt at building the full plugin from the brief

Claude’s first attempt at building the full plugin from the brief

It generated a working prototype remarkably fast. It even anticipated that I'd need an API key management feature and built one in without being asked. That moment shifted something in how I understood what these tools could do.

Phase 1: Getting the core loop to work

Phase 1: Getting the core loop to work

The idea was simple: extract copy from selected Figma layers, send it to an LLM, and return suggestions. Actually making that happen turned out to be a patience exercise.


I connected the plugin to Google's Gemini API using a free-tier key from AI Studio. It immediately started throwing errors on every request. The text extraction part worked fine, but the data never actually reached the API. And debugging with a free key that only allowed a handful of calls made the whole process painfully slow...

Error message showing the request failed to reach the Gemini API

Error message showing the request failed to reach the Gemini API

I asked our DevOps team for a production API key, which gave me room to iterate properly. From there, Claude Code took the lead on debugging while I focused on checking the logic behind each fix. My role wasn't really about writing code. It was more about keeping things clean, making sure the codebase stayed coherent instead of turning into spaghetti with every new patch.


After a few rounds of trial and error, the plugin finally worked. You could select text in Figma, click a button, and get copy suggestions right there in the panel.

Early working prototype generating copy suggestion from selected layers

Early working prototype generating copy suggestion from selected layers

Phase 2: Context is everything

Phase 2: Context is everything

Rather than generating a single suggestion, I designed the plugin to offer multiple options so designers can choose what fits best. I also added the ability to edit the copy directly before applying it.

Adding the feature to allow multiple copy suggestions and inline editing before applying

Adding the feature to allow multiple copy suggestions and inline editing before applying

A working plugin was a good start, but I wanted it to make the suggestions follow our specific copywriting standards, not just spit out generic AI text.


This is where I ran into an interesting technical constraint. Unlike ChatGPT where you can upload reference .md documents at runtime, Figma plugins run in a sandboxed environment. No access to local files. No ability to call external servers while running. Everything the plugin needs has to be baked into the code itself.


So the workaround was to embed our entire copywriting rulebook as string constants in the source code, and include it in every prompt sent to the LLM.


Adding the screenshot feature

The next challenge was more nuanced. Our copywriting rules are context-dependent. The guidelines for button labels are different from the ones for page headings, which are different from body copy. For the LLM to apply the right rules, it needed to see the visual context of where the text actually lived.


So I built a screenshot feature. The plugin captures the selected frame as an image and sends it alongside the extracted text, giving the LLM both the content and the spatial context to make better suggestions.


This turned out to be the hardest part of the entire project.


Figma's sandbox doesn't support standard browser APIs for image-to-text conversion. The Gemini API requires everything in text-based formats like JSON, so you can't just send raw image data through an HTTP request. Claude Code had to build a custom base64 encoding pipeline from scratch within the sandbox's limitations. This kicked off a chain of runtime errors that were hard to diagnose because the failures were happening silently.

Repeated errors as the plugin fails to send screenshot data to the LLM

Repeated errors as the plugin fails to send screenshot data to the LLM

What I contributed here was building a structured error feedback system into the plugin. When something failed, I could now see exactly where and why. That visibility changed everything. Instead of guessing at fixes, Claude Code could target the precise failure points.


Once the encoding was sorted out, I also expanded the suggestion interface. Instead of returning one recommendation, the plugin now shows multiple alternatives that designers can compare, pick from, or edit inline before applying.

Phase 3: Designing the experience

Phase 3: Designing the experience

By this point, the plugin worked well but looked rough. It was visually inconsistent. Basically it looked like it’s the ultimate AI-generated UI.

Limitation of editing UI with prompt: results still appear AI-generated

Limitation of editing UI with prompt: results still appear AI-generated

My first move was to refine the UI through prompting, describing what I wanted to Claude Code and going back and forth. Things improved, but they hit a ceiling. And for a tool that designers use every day, "decent" wasn't going to cut it.


So I tried something different. I used Claude to generate the plugin's interface directly on the Figma canvas, using our company's design system as a reference. There was one logistical snag though: the canvas rendering feature was only available through the browser extension, but my codebase was connected to the desktop app. I worked around it by screenshotting the current UI states and giving Claude specific layout parameters from our design system: 400×700 frame dimensions, 16px margins, consistent spacing tokens, and our component library styles.

After providing screenshots, Claude reconstructed the UI in Figma via code-to-canvas MCP

After providing screenshots, Claude reconstructed the UI in Figma via code-to-canvas MCP

After Claude generated the UI in Figma, I replaced most of it with our design system components and sent it back to Claude for refinement.

The result was a plugin that actually felt like it belonged in our product ecosystem. Visually aligned with everything else our designers use daily.

Impact

Impact

The plugin is now part of our team's daily workflow. Product designers and PMs use it consistently, not as a novelty but as a real part of how they write and refine UI copy.


I also received a special recognition award for the initiative. Which honestly felt surreal for something that started purely out of curiosity.

Three things this project taught me

Three things this project taught me

Directing AI is a skill in itself.

Claude Code could debug and build at a level way beyond what I could do alone. But it still needed human judgment. I had to evaluate its debugging strategies, give it context about where errors were likely coming from, and pull it back when it went down the wrong path. Knowing when to guide AI and when to step back is becoming a real design competency.

Testing is where the real quality lives.

When AI writes the code, the human's job shifts to quality assurance. I tested the plugin across dozens of edge cases, catching things the AI missed. It's not glamorous work, but it's probably the highest-leverage thing you can do in an AI-assisted workflow.

Without vision, you're just following the AI.

This is the one I keep coming back to. If I hadn't gone into this with a clear picture of the problem, the user, and the outcome I wanted, I would have just gone along with whatever Claude Code suggested. AI was the builder. I was the architect. That distinction matters more than ever.