My previous Dev.to post described MCP cross-service orchestration in general terms -- how form responses become Slack messages, Linear issues, or GitHub PRs through LLM-mediated chains. This post is a concrete implementation of that pattern: a structured client hearing form whose responses auto-generate a landing page wireframe in Figma.
The test case is GreenLeaf Analytics, an AI-powered SaaS for e-commerce cart recovery. A 28-question hearing form captures business context, target audience, content, design preferences, and assets. The responses feed into the Figma Plugin API to produce a multi-section wireframe in about 3 minutes.
The Architecture
Two MCP servers, one client, zero integrations.
MCP Client (Claude Desktop / Cursor)
|
|-- 1. FORMLOVA MCP: get_responses(form_id)
| → Structured JSON: 28 hearing answers
|
|-- 2. LLM: Interprets responses, builds Figma API commands
|
|-- 3. Figma MCP: create_new_file(name)
| → Empty Figma file
|
|-- 4. Figma MCP: use_figma(commands)
→ Wireframe sections built via Plugin API
FORMLOVA does not know about Figma. Figma does not know about FORMLOVA. The LLM reads the output of step 1 and constructs the input for steps 3-4. This is the same pattern from the cross-service orchestration post, but applied to a specific, testable workflow.
The Hearing Form: 5 Steps, 28 Questions
The hearing sheet is a multi-page form designed from the experience of over 100 website projects. The step order mirrors how a designer processes information.
| Step | Content | Purpose |
|---|---|---|
| 1 | Business context | Company name, industry, competitive advantage |
| 2 | Target audience and goals | Who visits, what they should do |
| 3 | Content to include | Headline, CTA copy, metrics, section selection |
| 4 | Design direction | Mood, colors, fonts, first-view layout, things to avoid |
| 5 | Assets and requests | Logo, photos, references, additional requirements |
Three questions have the highest impact on wireframe accuracy:
"Design elements to avoid" (Step 4). Asking what clients like produces vague answers. Asking what they dislike produces constraints. "No stock illustrations." "Nothing cluttered." One negative constraint narrows the design space more than three positive preferences.
"First-view layout" (Step 4). Five options: full-width photo overlay, split layout, illustration, text-centered, video background. Without options, clients say "something nice." With options, they make a concrete choice.
"Sections to include" (Step 3). A multi-select with 13 options -- hero, problem, solution, features, numbers, pricing, testimonials, flow, FAQ, team, blog, final CTA, contact. Only selected sections are generated in the wireframe.
The English hearing form is live: formlova.com/WBtSAMhw9G
Figma Plugin API: Key Implementation Patterns
The Figma MCP's use_figma tool executes code in the Figma Plugin API sandbox. There are specific constraints that shape the implementation.
Sandbox Limitations
- No
fetch()-- no external network requests - No external image loading -- all images become gray placeholders
- No
require()or module imports - Only fonts installed in the Figma environment are available
This is why the output is a wireframe, not a finished design. Images cannot be inserted programmatically, so every image position is a labeled placeholder frame.
The appendChild-then-FILL Constraint
This is the most important thing to know about Figma Plugin API Auto Layout. layoutSizingHorizontal: "FILL" only works after the frame has been added to an Auto Layout parent.
// Works
mainFrame.appendChild(section);
section.layoutSizingHorizontal = "FILL";
// Does not work -- FILL is silently ignored
section.layoutSizingHorizontal = "FILL";
mainFrame.appendChild(section);
This constraint applies to every FILL assignment in the entire wireframe -- sections, text nodes, card rows, everything.
Font Loading Is Mandatory
Text node manipulation requires pre-loaded fonts. Setting characters without loading the font throws an error.
await figma.loadFontAsync({ family: "Inter", style: "Regular" });
await figma.loadFontAsync({ family: "Inter", style: "Bold" });
await figma.loadFontAsync({ family: "Inter", style: "Semi Bold" });
// Must complete before any text creation
The Main Frame Structure
const mainFrame = figma.createFrame();
mainFrame.resize(1440, 100);
mainFrame.layoutMode = "VERTICAL";
mainFrame.primaryAxisSizingMode = "AUTO"; // Height grows with content
mainFrame.counterAxisSizingMode = "FIXED"; // Width stays at 1440px
mainFrame.itemSpacing = 0; // Sections touch edge-to-edge
Each section is a full-width child frame with its own padding, background color, and internal layout.
Mapping Hearing Responses to Wireframe Elements
The GreenLeaf Analytics test produced these mappings:
| Hearing Item | Wireframe Element | Implementation |
|---|---|---|
| Headline: "Stop losing sales. Start recovering them." | Hero heading | Direct text placement |
| CTA: "Start free trial" | Nav + Hero + Final CTA | Same text in 3 button instances |
| Main color: #059669 | CTA buttons, accents |
hexToRgb() → fills property |
| First view: "split" | Hero layout | layoutMode: "HORIZONTAL" |
| Mood: "Modern & tech-forward" | Spacing, dark sections | Config lookup table |
| 5 metrics (2,800+, 35%, $48M, etc.) | Numbers section | Parsed into large display text |
| Avoid: "No stock photos" | Placeholders only | No illustration elements generated |
| 3-tier pricing (Growth highlighted) | Pricing cards | Center card gets dark background + badge |
| Security badges: SOC 2, GDPR | Final CTA section | Badge elements in trust row |
Of 28 hearing items, 14 map directly to wireframe elements. The remaining 14 are used indirectly -- business description generates FAQ questions, target audience influences section copy, competitive advantages shape the solution section narrative.
Mood-to-Design Parameter Translation
The "mood" dropdown answer translates to concrete design parameters:
const moodConfigs = {
modern_tech: {
sectionPadding: 96,
cardBorderRadius: 12,
useDarkSections: true
},
warm_friendly: {
sectionPadding: 72,
cardBorderRadius: 16,
useDarkSections: false
},
luxury_refined: {
sectionPadding: 96,
cardBorderRadius: 4,
useDarkSections: true
},
minimal_clean: {
sectionPadding: 112,
cardBorderRadius: 8,
useDarkSections: false
}
};
This lookup table eliminates LLM interpretation variance. "Modern & tech-forward" always produces 12px border radius and dark sections.
Dynamic Section Construction
Only sections selected in the hearing form are generated. The builder pattern:
const builders: Record<string, (data: Response) => FrameNode> = {
hero: buildHero,
problem: buildProblem,
solution: buildSolution,
features: buildFeatures,
numbers: buildNumbers,
pricing: buildPricing,
cases: buildCases,
faq: buildFaq,
cta_bottom: buildCtaBottom,
// ... all 13 section types
};
for (const key of response.selectedSections) {
const builder = builders[key];
if (builder) {
const section = builder(response);
mainFrame.appendChild(section);
section.layoutSizingHorizontal = "FILL";
}
}
Each builder function reads from the hearing response to populate its content. The hero builder switches layout direction based on the first-view selection. The numbers builder parses metric strings into large display text. The pricing builder highlights the recommended tier.
Test Results
Test case: GreenLeaf Analytics (AI-powered cart recovery SaaS)
| Step | Time |
|---|---|
| Hearing form generation (Recipe 1) | ~2 min |
| Test response entry | ~1 min |
| Figma wireframe generation (Recipe 2) | ~3 min |
| Total | ~7 min |
Generated Figma file: GreenLeaf Analytics - LP Wireframe
Interactive prototype: View prototype
10 sections + navigation + footer, all with Auto Layout. Colors, spacing, and layout direction derived from hearing responses.
Honest Limitations
The generated wireframe is a starting point, not a deliverable.
No images. The sandbox constraint means every image position is a gray placeholder. For projects where photography defines the design direction, placeholders alone are insufficient.
Desktop only. The output is a 1440px wireframe. Mobile layouts require separate design work.
Typography needs refinement. Font sizes, line heights, and letter spacing are set to reasonable defaults, but they are not tuned to the brand. A designer still needs to adjust these.
The value proposition is time compression, not replacement. A wireframe that takes 3-4 hours to build from scratch appears in 3 minutes as a starting point. If the starting point is good enough, refinement takes 1 hour instead of 4.
Figma vs Canva
The same hearing data was tested with Canva MCP. Different tools for different stages.
Figma produces structurally accurate wireframes -- 1440px width, Auto Layout, each section in its own frame. A designer can continue directly from where the automation stopped.
Canva produces polished-looking slides from templates, but the output is not structured for production handoff. It works for proposals and pitch decks, not for design-to-development pipelines.
The Prompts
Both recipe prompts are published on FORMLOVA's Workflow Place. Recipe 1 generates the hearing form. Recipe 2 takes the latest response and builds the Figma wireframe. Copy and paste to run.
The full article with embedded Figma prototypes: Turn Site Design Hearings into Forms
If you are working with MCP cross-service flows, particularly involving Figma, I would be interested to hear about the patterns you have found useful. The Plugin API sandbox is a meaningful constraint that shapes what is possible.


Top comments (0)