Agent skill
figma-mcp-workflow
Standardize Figma-to-code workflow using Figma MCP - always get_design_context first, then screenshot, use project tokens not hardcoded values, validate 1:1 parity
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/development/figma-mcp-workflow-jewelshovan-pain-plus-site
SKILL.md
Figma MCP Workflow
This skill standardizes the Figma-to-code workflow using the Figma MCP (Model Context Protocol). Follow this process to ensure high-fidelity implementations that respect project conventions and design systems.
Workflow Overview
The workflow consists of 6 mandatory steps that must be executed in order:
- Fetch Design Context - Get structured node data from Figma
- Handle Truncation - Fetch metadata and re-query specific nodes if needed
- Get Visual Reference - Capture screenshot for validation
- Download Assets - Retrieve images/SVGs from localhost sources
- Implement - Build using project conventions and tokens
- Validate - Ensure 1:1 parity with Figma design
Step-by-Step Process
Step 1: Fetch Design Context
ALWAYS start with get_design_context to retrieve structured node data including styles, layout, and component hierarchy.
// Call the Figma MCP tool
mcp__figma-desktop__get_design_context({
nodeId: "123:456", // Extract from URL or use current selection
clientLanguages: "typescript,javascript",
clientFrameworks: "react"
})
What you'll receive:
- Component hierarchy and structure
- Style properties (colors, typography, spacing, borders)
- Layout data (flexbox, grid, positioning)
- Text content and asset references
- React + Tailwind code (use as reference, not final implementation)
Important: The returned React + Tailwind code is a design reference, not production-ready code. You must adapt it to project conventions.
Step 2: Handle Truncation (If Needed)
If the response is too large and gets truncated, you'll see a message indicating this. When this happens:
- Fetch metadata to get a node map:
mcp__figma-desktop__get_metadata({
nodeId: "123:456", // Parent node or page
clientLanguages: "typescript,javascript",
clientFrameworks: "react"
})
-
Identify specific child nodes from the XML structure
-
Re-fetch each node individually using
get_design_context:
// Fetch specific nodes that were truncated
mcp__figma-desktop__get_design_context({
nodeId: "123:789", // Specific child node
clientLanguages: "typescript,javascript",
clientFrameworks: "react"
})
Step 3: Get Visual Reference
Always capture a screenshot for visual validation:
mcp__figma-desktop__get_screenshot({
nodeId: "123:456",
clientLanguages: "typescript,javascript",
clientFrameworks: "react"
})
Use the screenshot to:
- Verify spacing and alignment
- Validate color accuracy
- Confirm typography hierarchy
- Check responsive behavior
- Reference during implementation
Step 4: Download Assets
If Figma MCP returns localhost sources for images or SVGs:
DO:
- Download assets from provided localhost URLs
- Save to appropriate project directories (
public/assets/,src/assets/) - Use relative paths in implementation
- Optimize assets if needed (compress images, clean SVGs)
DO NOT:
- Create placeholder images when real assets are provided
- Import new icon packages (Lucide, Heroicons, etc.)
- Use external CDN links for assets available locally
Example:
// Figma MCP provides: http://localhost:PORT/asset.svg
// Download and save to: /public/assets/icons/logo.svg
// Use in code:
<img src="/assets/icons/logo.svg" alt="Logo" />
Step 5: Implement Using Project Conventions
This is where you translate the Figma design into production code. Follow these rules:
5.1 Use Project Color Tokens
NEVER hardcode colors. Use project tokens from src/index.css (Tailwind v4 @theme block).
Wrong:
<div className="bg-blue-500 text-white border-gray-200">
Correct:
<div className="bg-[hsl(var(--color-primary))] text-[hsl(var(--color-primary-foreground))] border-[hsl(var(--color-border))]">
Common project tokens:
/* From src/index.css @theme block */
--color-background: /* Page background */
--color-foreground: /* Main text color */
--color-primary: /* Brand primary */
--color-primary-foreground: /* Text on primary */
--color-secondary: /* Secondary accent */
--color-secondary-foreground: /* Text on secondary */
--color-muted: /* Muted backgrounds */
--color-muted-foreground: /* Muted text */
--color-accent: /* Accent color */
--color-accent-foreground: /* Text on accent */
--color-border: /* Border color */
--color-input: /* Input borders */
--color-ring: /* Focus rings */
--color-destructive: /* Error/delete */
--color-destructive-foreground: /* Text on destructive */
Token usage examples:
// Backgrounds
className="bg-[hsl(var(--color-background))]"
className="bg-[hsl(var(--color-primary))]"
className="bg-[hsl(var(--color-muted))]"
// Text colors
className="text-[hsl(var(--color-foreground))]"
className="text-[hsl(var(--color-primary))]"
className="text-[hsl(var(--color-muted-foreground))]"
// Borders
className="border-[hsl(var(--color-border))]"
className="border-[hsl(var(--color-input))]"
// Focus states
className="focus:ring-[hsl(var(--color-ring))]"
5.2 Reuse Existing Components
NEVER reinvent shadcn components. Check components/ui/ first.
Available components:
Button- All button variantsCard,CardHeader,CardTitle,CardDescription,CardContent,CardFooterInput,Textarea,SelectBadge- Labels and tagsDialog,Sheet,Popover,DropdownMenuTabs,Accordion,CollapsibleAvatar,Separator,SkeletonToast,Alert,AlertDialog- And more...
Wrong:
<div className="rounded-lg bg-[hsl(var(--color-primary))] px-4 py-2 text-[hsl(var(--color-primary-foreground))] hover:bg-[hsl(var(--color-primary))]/90">
Click me
</div>
Correct:
import { Button } from "@/components/ui/button"
<Button>Click me</Button>
Component reuse checklist:
- Check if shadcn component exists in
components/ui/ - Use component variants (size, variant props)
- Extend with composition, not duplication
- Import types for proper TypeScript support
5.3 Use Typography and Spacing Tokens
Typography scale:
// Headings
<h1 className="text-4xl font-bold">
<h2 className="text-3xl font-semibold">
<h3 className="text-2xl font-semibold">
<h4 className="text-xl font-semibold">
// Body text
<p className="text-base">
<p className="text-sm text-[hsl(var(--color-muted-foreground))]">
<p className="text-xs text-[hsl(var(--color-muted-foreground))]">
Spacing scale:
// Use Tailwind's spacing scale (based on 0.25rem units)
gap-4 // 1rem
gap-6 // 1.5rem
gap-8 // 2rem
p-4 // padding: 1rem
px-6 // padding-left/right: 1.5rem
py-8 // padding-top/bottom: 2rem
space-y-4 // vertical spacing between children
5.4 Respect Project Architecture
Routing:
- Use React Router patterns already in the project
- Don't introduce new routing libraries
State Management:
- Follow existing patterns (Context, hooks, etc.)
- Don't introduce Redux/Zustand unless discussed
File Structure:
- Components in
src/components/ - Pages/routes in
src/pages/ - Utilities in
src/lib/ - Types in component files or
src/types/
TypeScript:
- Always use TypeScript
- Define proper interfaces for props
- Avoid
anytypes
Step 6: Validate 1:1 Parity
Before marking implementation complete, validate against the Figma screenshot:
Validation Checklist
Visual Parity:
- Layout matches Figma (spacing, alignment, sizing)
- Colors match exactly (use screenshot color picker if needed)
- Typography hierarchy is correct (sizes, weights, line heights)
- Borders, shadows, and effects match
- Icons and images are positioned correctly
- Responsive behavior matches design intentions
Code Quality:
- No hardcoded colors (all using CSS variables)
- No hardcoded spacing values (using Tailwind scale)
- Reusing shadcn components where applicable
- Proper TypeScript types defined
- Assets downloaded and referenced correctly
- No new icon packages imported
- Follows project file structure
Accessibility:
- Semantic HTML elements used
- Proper ARIA labels where needed
- Keyboard navigation works
- Focus states visible
- Color contrast meets WCAG standards
Performance:
- Images optimized
- No unnecessary re-renders
- Proper React key props in lists
- Lazy loading for heavy components
Complete Example
Scenario
User provides Figma URL: https://figma.com/design/ABC123/MyApp?node-id=1-2
Implementation
Step 1: Extract node ID and fetch design context
Node ID: 1:2
Call get_design_context with:
- nodeId: "1:2"
- clientLanguages: "typescript,javascript"
- clientFrameworks: "react"
Step 2: Analyze response Response includes:
- Card component with button
- Primary color: #3B82F6
- Text: "Get Started"
- Icon: ChevronRight
Step 3: Get screenshot
Call get_screenshot with nodeId "1:2" for visual reference
Step 4: Download assets
If icon is provided as localhost source, download to public/assets/icons/
Step 5: Implement
Wrong approach (using Figma MCP output as-is):
// Don't do this!
<div className="bg-blue-500 text-white rounded-lg p-6">
<h2 className="text-2xl font-bold mb-2">Welcome</h2>
<p className="text-gray-100 mb-4">Get started with our platform</p>
<button className="bg-white text-blue-500 px-4 py-2 rounded-md flex items-center gap-2">
Get Started
<ChevronRight /> {/* New icon import! */}
</button>
</div>
Correct approach (project conventions):
import { Button } from "@/components/ui/button"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
export function WelcomeCard() {
return (
<Card className="bg-[hsl(var(--color-primary))] text-[hsl(var(--color-primary-foreground))]">
<CardHeader>
<CardTitle className="text-2xl">Welcome</CardTitle>
<CardDescription className="text-[hsl(var(--color-primary-foreground))]/90">
Get started with our platform
</CardDescription>
</CardHeader>
<CardContent>
<Button
variant="secondary"
className="flex items-center gap-2"
>
Get Started
<img
src="/assets/icons/chevron-right.svg"
alt=""
className="w-4 h-4"
/>
</Button>
</CardContent>
</Card>
)
}
Step 6: Validate
- Card component reused from shadcn
- Button component reused with variant
- Colors use CSS variables (--color-primary)
- Icon downloaded from localhost, not imported
- Layout matches screenshot
- TypeScript interface defined (if props needed)
Anti-Patterns to Avoid
Don't Hardcode Colors
// WRONG
<div className="bg-blue-500 text-white border-gray-200">
// CORRECT
<div className="bg-[hsl(var(--color-primary))] text-[hsl(var(--color-primary-foreground))] border-[hsl(var(--color-border))]">
Don't Import New Icon Libraries
// WRONG
import { ChevronRight } from "lucide-react"
// CORRECT - Use asset from Figma
<img src="/assets/icons/chevron-right.svg" alt="" className="w-4 h-4" />
Don't Recreate Existing Components
// WRONG
<div className="inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold">
New
</div>
// CORRECT
import { Badge } from "@/components/ui/badge"
<Badge>New</Badge>
Don't Skip Visual Validation
// WRONG - Implementing without screenshot reference
// CORRECT - Always get screenshot and validate against it
Don't Create Placeholders When Assets Exist
// WRONG
<div className="w-full h-64 bg-gray-200 flex items-center justify-center">
Image placeholder
</div>
// CORRECT - Use provided localhost asset
<img src="/assets/images/hero.png" alt="Hero" className="w-full h-64 object-cover" />
Quick Reference
Token Mapping
| Figma MCP Output | Project Token |
|---|---|
bg-blue-500 |
bg-[hsl(var(--color-primary))] |
text-white |
text-[hsl(var(--color-primary-foreground))] |
bg-gray-100 |
bg-[hsl(var(--color-muted))] |
text-gray-600 |
text-[hsl(var(--color-muted-foreground))] |
border-gray-200 |
border-[hsl(var(--color-border))] |
bg-red-500 |
bg-[hsl(var(--color-destructive))] |
Component Mapping
| Figma MCP Pattern | shadcn Component |
|---|---|
| Card with header/body | Card, CardHeader, CardContent |
| Button | Button with variants |
| Input field | Input or Textarea |
| Dropdown | Select or DropdownMenu |
| Modal | Dialog or Sheet |
| Tag/Label | Badge |
| Divider | Separator |
| Loading state | Skeleton |
Workflow Checklist
- 1. Fetch design context with
get_design_context - 2. Handle truncation if needed with
get_metadata - 3. Get screenshot with
get_screenshot - 4. Download all localhost assets
- 5. Map colors to project tokens
- 6. Reuse shadcn components
- 7. Follow project structure
- 8. Validate against screenshot
- 9. Check TypeScript types
- 10. Verify no hardcoded values
Summary
Always remember:
- Figma MCP output is a reference, not final code
- Never hardcode colors - use CSS variables
- Never import new icon packages - use Figma assets
- Always reuse shadcn components
- Always validate against screenshot
- Strive for pixel-perfect parity
By following this workflow, you'll ensure consistent, maintainable implementations that respect both the design system and project conventions.
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
Didn't find tool you were looking for?