figma-to-ai-prompter
Generate optimized prompts from Figma designs for AI prototyping tools like Lovable, Figma Make, Pencil.dev, Paper.design and Google Stitch
How do I install this agent skill?
npx skills add https://github.com/reason-machines/design-skills --skill figma-to-ai-prompterIs this agent skill safe to install?
- Gen Agent Trust Hubpass
The skill provides templates and scripts to convert Figma designs into optimized prompts for various AI tools. It uses sensitive Figma API tokens via environment variables and interacts with the official Figma API. It is susceptible to indirect prompt injection if the source Figma designs contain malicious data intended to manipulate the downstream AI models.
- Socketpass
No alerts
- Snykwarn
Risk: MEDIUM · 1 issue
What does this agent skill do?
Figma to AI Prompter
Skill by ara.so — Design Skills collection.
Figma-to-AI Prompter converts Figma designs into structured, token-optimized prompts for AI prototyping tools. It bridges the design-to-code gap by extracting design structure and generating targeted prompts for Lovable, Figma Make, Pencil.dev, Paper.design, and Google Stitch — achieving up to 97% reduction in prompt size and 18% reduction in execution cost.
What It Does
- Extracts Figma design structure (layouts, components, styles)
- Transforms design data into tool-specific prompts
- Optimizes token usage through MCP text context instead of frame attachments
- Supports multiple AI prototyping platforms with different models and output formats
- Validates generated prototypes against original designs
Installation
# Clone the repository
git clone https://github.com/royvillasana/figma-to-ai-prompter.git
cd figma-to-ai-prompter
# Install dependencies (if applicable)
npm install
Project Structure
figma-to-ai-prompter/
├── prompts/ # Tool-specific prompt templates
│ ├── figma-to-lovable.md
│ ├── figma-to-figmamake.md
│ ├── figma-to-pencil.md
│ └── figma-to-paper.md
├── examples/ # Sample inputs and outputs
│ ├── input-figma.json
│ └── output-prompt.md
├── scripts/ # Transformation utilities
│ └── transform.js
└── README.md
Supported AI Tools
| Tool | Model | Output | Token Model |
|---|---|---|---|
| Lovable | Claude | Full-stack React app | Credit per message |
| Figma Make | Claude | Interactive HTML prototype | Figma subscription |
| Pencil.dev | AI | Production React components | Credit per generation |
| Paper.design | Agent | HTML/CSS canvas + code export | Agent tool calls |
| Google Stitch | Gemini 2.5 | Responsive UI → Figma/HTML | Limited monthly generations |
Core Workflow
1. Extract Figma Design Data
Export your Figma design structure as JSON or use the Figma API:
// Using Figma API
const FIGMA_TOKEN = process.env.FIGMA_TOKEN;
const FILE_KEY = 'your-file-key';
async function fetchFigmaFile(fileKey) {
const response = await fetch(
`https://api.figma.com/v1/files/${fileKey}`,
{
headers: { 'X-Figma-Token': FIGMA_TOKEN }
}
);
return await response.json();
}
const figmaData = await fetchFigmaFile(FILE_KEY);
2. Transform to Structured Context
Use MCP text context blocks instead of frame attachments for token efficiency:
// scripts/transform.js
function extractDesignStructure(figmaNode) {
return {
type: figmaNode.type,
name: figmaNode.name,
layout: {
width: figmaNode.absoluteBoundingBox?.width,
height: figmaNode.absoluteBoundingBox?.height,
x: figmaNode.absoluteBoundingBox?.x,
y: figmaNode.absoluteBoundingBox?.y
},
styles: extractStyles(figmaNode),
children: figmaNode.children?.map(extractDesignStructure) || []
};
}
function extractStyles(node) {
return {
fills: node.fills,
strokes: node.strokes,
effects: node.effects,
cornerRadius: node.cornerRadius,
constraints: node.constraints
};
}
function generatePromptContext(structure) {
return `
Design Structure:
- Component: ${structure.name}
- Type: ${structure.type}
- Layout: ${structure.layout.width}x${structure.layout.height}
- Styles: ${JSON.stringify(structure.styles, null, 2)}
${structure.children.length > 0 ? `- Children: ${structure.children.length} elements` : ''}
`.trim();
}
// Example usage
const designStructure = extractDesignStructure(figmaData.document);
const promptContext = generatePromptContext(designStructure);
console.log(promptContext);
3. Generate Tool-Specific Prompts
For Lovable (Claude → Full-stack React)
# Lovable Prompt Template
## Design Context
{DESIGN_STRUCTURE}
## Requirements
- Create a full-stack React application
- Use Tailwind CSS for styling
- Match the exact layout and spacing from the design
- Implement responsive behavior for mobile/tablet/desktop
- Include all interactive states (hover, active, disabled)
## Component Hierarchy
{COMPONENT_TREE}
## Style Specifications
{COLOR_PALETTE}
{TYPOGRAPHY}
{SPACING_SYSTEM}
## Interactions
{INTERACTIVE_ELEMENTS}
Please generate a complete React application with:
1. Component structure matching the design hierarchy
2. Tailwind classes for all styling
3. Proper state management for interactions
4. Responsive breakpoints
For Figma Make (Claude → HTML Prototype)
# Figma Make Prompt Template
## Design Analysis
{DESIGN_STRUCTURE}
## Output Requirements
- Generate interactive HTML/CSS prototype
- Use vanilla JavaScript for interactions
- Match pixel-perfect layout from Figma
- Include all design tokens (colors, spacing, typography)
- Implement hover and click states
## Layout Structure
{FRAME_HIERARCHY}
## Style Guide
{DESIGN_TOKENS}
## Validation
Once generated, compare against published Figma Make link:
{FIGMA_MAKE_URL}
Identify discrepancies in:
- Spacing and alignment
- Color values
- Typography
- Interactive behavior
For Pencil.dev (AI → Production React)
# Pencil.dev Prompt Template
## Component Requirements
{COMPONENT_SPECS}
## Design System Integration
- Use existing design tokens: {TOKEN_PATH}
- Follow component patterns: {PATTERN_LIBRARY}
- Ensure accessibility (WCAG 2.1 AA)
## Technical Constraints
- React 18+
- TypeScript
- Styled-components or CSS modules
- Props interface for customization
## Design Context
{DESIGN_STRUCTURE}
Generate production-ready React component with:
1. Full TypeScript types
2. Prop documentation
3. Storybook stories
4. Unit tests
4. Token Optimization Strategy
Avoid frame attachments (adds 300-500 hidden tokens):
// ❌ Token-heavy approach
const prompt = `Generate this design: [Frame attachment]`;
// Hidden cost: ~500 tokens + interpretation overhead
// ✅ Optimized approach using MCP text context
const prompt = `
Generate design with:
- Container: 1200px max-width, centered
- Header: 64px height, #1A1A1A background
- Grid: 3 columns, 24px gap
- Cards: white bg, 8px radius, 16px padding
`;
// Cost: ~45 tokens, precise instructions
Structured extraction example:
function optimizePromptGeneration(figmaNode) {
// Extract only essential information
const essential = {
layout: `${figmaNode.absoluteBoundingBox.width}x${figmaNode.absoluteBoundingBox.height}`,
background: figmaNode.fills?.[0]?.color,
padding: figmaNode.paddingLeft || 0,
gap: figmaNode.itemSpacing || 0,
cornerRadius: figmaNode.cornerRadius || 0
};
// Generate minimal, structured prompt
return Object.entries(essential)
.filter(([_, value]) => value !== undefined && value !== 0)
.map(([key, value]) => `${key}: ${JSON.stringify(value)}`)
.join('\n');
}
// Result: ~45 tokens vs 500+ with frame attachment
Configuration
Environment Variables
# .env
FIGMA_TOKEN=your_figma_personal_access_token
FIGMA_FILE_KEY=your_file_key
TARGET_TOOL=lovable # lovable | figmamake | pencil | paper | stitch
Tool-Specific Settings
// config.js
module.exports = {
lovable: {
framework: 'react',
styling: 'tailwind',
maxTokens: 4000
},
figmamake: {
outputFormat: 'html',
includeInteractions: true,
validationURL: process.env.FIGMA_MAKE_URL
},
pencil: {
typescript: true,
testFramework: 'jest',
designSystem: 'custom'
}
};
Common Patterns
Pattern 1: Complete Figma-to-Prompt Pipeline
const { fetchFigmaFile, extractDesignStructure, generatePromptContext } = require('./scripts/transform');
async function generateAIPrompt(fileKey, targetTool) {
// 1. Fetch Figma data
const figmaData = await fetchFigmaFile(fileKey);
// 2. Extract structure
const structure = extractDesignStructure(figmaData.document);
// 3. Generate optimized context
const context = generatePromptContext(structure);
// 4. Load tool-specific template
const template = require(`./prompts/figma-to-${targetTool}.md`);
// 5. Merge context with template
const finalPrompt = template.replace('{DESIGN_STRUCTURE}', context);
return finalPrompt;
}
// Usage
const prompt = await generateAIPrompt('abc123', 'lovable');
console.log(prompt);
Pattern 2: Iterative Validation Loop
async function validateAndRefine(initialPrompt, figmaMakeURL) {
let currentPrompt = initialPrompt;
let iteration = 0;
const maxIterations = 3;
while (iteration < maxIterations) {
console.log(`Iteration ${iteration + 1}: Generating prototype...`);
// Send to AI tool (pseudo-code)
const generatedCode = await sendToAITool(currentPrompt);
// Validate against Figma Make
const validationPrompt = `
Compare this generated code against the published Figma Make design:
${figmaMakeURL}
Generated code:
${generatedCode}
List specific discrepancies in:
1. Layout and spacing
2. Colors and typography
3. Component structure
4. Interactive behavior
Provide updated prompt instructions to fix discrepancies.
`;
const feedback = await sendToAITool(validationPrompt);
if (feedback.includes('no discrepancies')) {
console.log('✅ Validation passed');
break;
}
// Refine prompt based on feedback
currentPrompt = `${currentPrompt}\n\n## Corrections from validation:\n${feedback}`;
iteration++;
}
return currentPrompt;
}
Pattern 3: Component Extraction for Design Systems
function extractReusableComponents(figmaNode) {
const components = [];
function traverse(node) {
if (node.type === 'COMPONENT' || node.type === 'COMPONENT_SET') {
components.push({
name: node.name,
id: node.id,
description: node.description,
props: extractComponentProps(node),
variants: node.children?.map(child => child.name) || []
});
}
node.children?.forEach(traverse);
}
traverse(figmaNode);
return components;
}
function extractComponentProps(componentNode) {
const props = {};
// Extract from component properties
if (componentNode.componentPropertyDefinitions) {
Object.entries(componentNode.componentPropertyDefinitions).forEach(([key, def]) => {
props[key] = {
type: def.type,
defaultValue: def.defaultValue,
values: def.variantOptions || []
};
});
}
return props;
}
// Generate component library prompt
const components = extractReusableComponents(figmaData.document);
const componentPrompt = `
Create a design system with these components:
${components.map(c => `
## ${c.name}
Props: ${JSON.stringify(c.props)}
Variants: ${c.variants.join(', ')}
`).join('\n')}
`;
Troubleshooting
Issue: High Token Usage
Problem: Prompts exceeding 1000+ tokens
Solution: Use MCP text context instead of frame attachments
// Instead of attaching frames, extract structured data
const minimalContext = {
dimensions: `${width}x${height}`,
colors: extractColorPalette(node),
spacing: extractSpacingValues(node),
typography: extractTextStyles(node)
};
// Generate compact prompt
const prompt = `Create layout: ${JSON.stringify(minimalContext)}`;
Issue: Inconsistent AI Output
Problem: Generated code doesn't match design
Solution: Add explicit constraints and validation
const prompt = `
${basePrompt}
STRICT REQUIREMENTS:
- Header height must be exactly 64px
- Use #1A1A1A for background (not approximations)
- Grid gap must be 24px (verify in DevTools)
- Card padding: 16px all sides
Validation: Compare output against ${figmaMakeURL}
`;
Issue: Missing Design Tokens
Problem: Colors/spacing not extracted correctly
Solution: Deep traverse all style properties
function extractAllStyles(node, styles = {}) {
// Extract fills
if (node.fills) {
node.fills.forEach(fill => {
if (fill.type === 'SOLID') {
const hex = rgbToHex(fill.color);
styles.colors = styles.colors || [];
if (!styles.colors.includes(hex)) {
styles.colors.push(hex);
}
}
});
}
// Extract text styles
if (node.style) {
styles.typography = styles.typography || [];
styles.typography.push({
fontFamily: node.style.fontFamily,
fontSize: node.style.fontSize,
fontWeight: node.style.fontWeight,
lineHeight: node.style.lineHeightPx
});
}
// Recurse
node.children?.forEach(child => extractAllStyles(child, styles));
return styles;
}
Issue: Tool-Specific Formatting
Problem: Different tools require different prompt formats
Solution: Use template system with tool-specific processors
const toolProcessors = {
lovable: (context) => `
# React App Requirements
${context}
Generate with:
- Vite + React 18
- Tailwind CSS
- Component composition
`,
figmamake: (context) => `
# HTML Prototype
${context}
Output:
- Semantic HTML5
- Vanilla CSS (no preprocessors)
- Minimal JavaScript
`,
pencil: (context) => `
# Production Component
${context}
Include:
- TypeScript types
- Prop validation
- Accessibility
- Tests
`
};
const finalPrompt = toolProcessors[targetTool](designContext);
Performance Benchmarks
- Prompt size reduction: 91-97% (from 500-1500 tokens → ~45 tokens)
- Execution cost: -18% (from ~40,782 → ~33,508 tokens)
- Validation flow: ~90 tokens total (initial + corrections)
Best Practices
- Always use structured text context over frame attachments
- Include validation URLs for iterative refinement
- Extract design tokens separately for reusability
- Test prompts with minimal examples before full designs
- Version control prompts alongside design files
- Document tool-specific quirks in template comments
Resources
- Figma API Documentation
- Lovable Documentation
- Figma Make Guide
- Author: Roy Villasana (royvillasana@gmail.com)
How can the creator link this skill?
Add the canonical catalog link to the repository README so users can inspect current installs and available audits. The publishing guide covers the complete discovery path.
<a href="https://skillzs.dev/skills/reason-machines/design-skills/figma-to-ai-prompter">View figma-to-ai-prompter on skillZs</a>