# Moai Domain Figma

> Figma design system integration with API automation, design tokens, and component libraries for scalable design infrastructure. Enhanced MCP integration, error handling, and performance optimization.

- Skill: `majiayu000/moai-domain-figma` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds add majiayu000/moai-domain-figma`
- Raw SKILL.md: https://api.skillmd.com/api/skills/majiayu000/moai-domain-figma/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Design & Media
- Author: majiayu000 (https://skillmd.com/u/majiayu000)
- Updated: 2026-09-09
- Page: https://skillmd.com/skills/majiayu000/moai-domain-figma

---



# Design Systems & Figma Integration - Advanced MCP Patterns

**Enterprise design system architecture with Figma API, design tokens, and automation**

> **Primary Agent**: design-expert, component-designer
> **Stack**: Figma API 2025+, MCP integration, design tokens, component libraries, design-to-code automation
> **Keywords**: figma, design-system, design-tokens, components, design-to-code, mcp, automation
> **Updated**: Enhanced MCP tool patterns, error handling, performance optimization (v4.1.0)

## Level 1: Quick Reference

### When to Use This Skill

- ✅ Building enterprise design systems with Figma as SSOT
- ✅ Automating design-to-code workflows with MCP tools
- ✅ Managing design tokens and component libraries
- ✅ Integrating Figma with development pipelines
- ✅ Scaling design across teams with automation
- ✅ Exporting design assets and generating component code

### Core Capabilities

- **Figma MCP Integration**: Direct API access via MCP tools
- **Design System Architecture**: Design token management, component organization
- **Figma API Automation**: File manipulation, asset export, component generation
- **Design Tokens**: CSS variables, JSON, SCSS export strategies
- **Design-to-Code**: Automated component generation from Figma designs
- **Performance Optimization**: Caching, parallel requests, conditional loading

### MCP Tools Overview

| Tool | Purpose | Use Cases |
|------|---------|-----------|
| `get_design_context` | Retrieve design metadata + generated code | Component generation, design inspection |
| `get_screenshot` | Export design as PNG/SVG | Asset export, visual documentation |
| `get_variable_defs` | Extract design tokens/variables | Token syncing, design system export |
| `export_components` | Batch export multiple components | Library generation, code scaffolding |

---

## Level 2: Practical Implementation

### Design System Patterns

Design systems connect design and development with MCP automation:

- **Single Source of Truth**: Figma as SSOT for design with automated syncing
- **Token Management**: Extract from Figma variables → CSS custom properties, JSON
- **Component Library**: Reusable design components with automated code generation
- **Documentation**: Auto-generated API docs from component metadata
- **Pipeline Integration**: Design changes → automatic code updates

### MCP Tool Invocation Patterns

#### Pattern 1: Sequential Calls (Default)

Use when output of one call feeds into the next:

```typescript
// Step 1: Get design context (metadata + generated code)
const context = await mcp__figma__get_design_context({
  nodeId: "689:1242",
  clientLanguages: "typescript",
  dirForAssetWrites: "./src/generated/figma-assets" // REQUIRED!
});

// Step 2: Get screenshot based on context
const screenshot = await mcp__figma__get_screenshot({
  nodeId: context.nodeId,
  format: "png",
  scale: 2
});

// Step 3: Extract variables from context
const tokens = context.variables || [];
```

**When to use**: Design inspection → Asset export → Token extraction

#### Pattern 2: Parallel Calls (Performance Optimization)

Use for independent requests to reduce total execution time (20-30% speedup):

```typescript
// Fetch multiple independent resources in parallel
const [context, variables, screenshot] = await Promise.all([
  mcp__figma__get_design_context({
    nodeId: "689:1242",
    clientLanguages: "typescript",
    dirForAssetWrites: "./src/generated/figma-assets"
  }),
  mcp__figma__get_variable_defs({
    fileId: "abc123xyz",
    teamId: "team-456"
  }),
  mcp__figma__get_screenshot({
    nodeId: "689:1242",
    format: "svg"
  })
]);

// All requests complete simultaneously
console.log("Parallel execution time: ~3-4s vs sequential 9-12s");
```

**Speedup calculation**:
- Sequential: get_design_context (3-4s) + get_variable_defs (2-3s) + get_screenshot (3-4s) = 8-11s
- Parallel: max(3-4s, 2-3s, 3-4s) = 3-4s
- **Improvement**: 60-70% faster

#### Pattern 3: Conditional Loading (Resource Optimization)

Skip unnecessary calls based on requirements:

```typescript
// Only call what you need
const config = {
  needsCode: true,
  needsAssets: false,
  needsTokens: true
};

const requests = [];

// Conditionally add only required calls
if (config.needsCode || config.needsAssets) {
  requests.push(
    mcp__figma__get_design_context({
      nodeId: "689:1242",
      clientLanguages: "typescript",
      dirForAssetWrites: config.needsAssets ? "./assets" : undefined
    })
  );
}

if (config.needsTokens) {
  requests.push(
    mcp__figma__get_variable_defs({
      fileId: "abc123xyz"
    })
  );
}

const results = await Promise.all(requests);
```

**Benefit**: Reduce API calls by 30-50% based on actual needs

### Parameter Guidelines & Validation

#### Required Parameters

**`dirForAssetWrites`** (CRITICAL - Common Error Source)

```typescript
// ❌ WRONG: Will cause 400 Bad Request
const context = await mcp__figma__get_design_context({
  nodeId: "689:1242",
  clientLanguages: "typescript"
  // Missing dirForAssetWrites!
});

// ✅ CORRECT: Specify asset output directory
const context = await mcp__figma__get_design_context({
  nodeId: "689:1242",
  clientLanguages: "typescript",
  dirForAssetWrites: "/tmp/figma-assets" // Required even if not using assets
});
```

**Why**: MCP tool needs to know where to write exported assets (even if not used)

#### NodeId Format Validation

```typescript
// NodeId examples (format: "parent-id:component-id")
const validNodeIds = [
  "689:1242",        // Simple component
  "0:1",             // Page/root
  "689:1242:5678",   // Nested instance
  "I123:456:789"     // Copy instance
];

// Validation pattern
function validateNodeId(nodeId: string): boolean {
  // Format: alphanumeric:digit, optionally nested
  return /^[a-zA-Z0-9]+:[0-9]+(:[0-9a-zA-Z:]+)?$/.test(nodeId);
}

if (!validateNodeId(nodeId)) {
  throw new Error(`Invalid nodeId format: ${nodeId}`);
}
```

#### ClientLanguages/Frameworks Auto-Detection

```typescript
// Auto-detect from project context
function detectFramework(projectPath: string): string {
  const packageJson = require(`${projectPath}/package.json`);

  if (packageJson.dependencies?.react) {
    return packageJson.dependencies.typescript ? "typescript" : "javascript";
  }

  if (packageJson.dependencies?.vue) {
    return "typescript"; // Vue 3 + TS recommended
  }

  if (packageJson.dependencies?.["@angular/core"]) {
    return "typescript"; // Angular always TS
  }

  return "typescript"; // Default
}

// Usage
const clientLanguages = detectFramework("./");
const context = await mcp__figma__get_design_context({
  nodeId: "689:1242",
  clientLanguages, // Auto-detected
  dirForAssetWrites: "./src/generated"
});
```

---

## Level 3: Advanced Patterns & Error Handling

### Error Handling Strategies

#### Common Error: 400 Bad Request - Missing dirForAssetWrites

```typescript
// Error symptoms:
// - 400 Bad Request
// - "dirForAssetWrites is required"
// - Asset export fails silently

// Solution
try {
  const context = await mcp__figma__get_design_context({
    nodeId: "689:1242",
    clientLanguages: "typescript",
    dirForAssetWrites: "./src/generated/figma-assets" // Add this!
  });
} catch (error) {
  if (error.message.includes("dirForAssetWrites")) {
    console.error("Missing dirForAssetWrites parameter");
    // Provide default asset directory
    return await mcp__figma__get_design_context({
      nodeId: "689:1242",
      clientLanguages: "typescript",
      dirForAssetWrites: "/tmp/figma-assets" // Fallback
    });
  }
  throw error;
}
```

#### Rule: Separate get_screenshot and get_variable_defs

**Do NOT call in sequence unless necessary** - Use parallel calls instead:

```typescript
// ❌ INEFFICIENT: Sequential calls
const screenshot1 = await mcp__figma__get_screenshot({nodeId: "id1"});
const vars1 = await mcp__figma__get_variable_defs({fileId: "file1"});
const screenshot2 = await mcp__figma__get_screenshot({nodeId: "id2"});
const vars2 = await mcp__figma__get_variable_defs({fileId: "file1"});
// Total time: 16-20s (sequential)

// ✅ EFFICIENT: Parallel calls grouped by type
const [screenshots, variables] = await Promise.all([
  Promise.all([
    mcp__figma__get_screenshot({nodeId: "id1"}),
    mcp__figma__get_screenshot({nodeId: "id2"})
  ]),
  mcp__figma__get_variable_defs({fileId: "file1"})
]);
// Total time: 3-4s (parallel)
```

**Benefits**: 4-5x faster for batch operations

#### Rate Limiting Handling

```typescript
// Exponential backoff for rate-limited requests
async function callWithBackoff(
  fn: () => Promise<any>,
  maxRetries = 3,
  initialDelay = 1000
): Promise<any> {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await fn();
    } catch (error) {
      if (error.status === 429) { // Rate limited
        const delay = initialDelay * Math.pow(2, attempt);
        console.log(`Rate limited. Retrying in ${delay}ms...`);
        await new Promise(resolve => setTimeout(resolve, delay));
      } else {
        throw error;
      }
    }
  }
  throw new Error(`Max retries exceeded`);
}

// Usage
const screenshot = await callWithBackoff(() =>
  mcp__figma__get_screenshot({nodeId: "689:1242"})
);
```

### Performance Optimization Tips

#### Caching Strategy

```typescript
// Cache metadata with different TTLs based on change frequency
const cacheConfig = {
  metadata: { ttl: 72 * 3600 }, // Design rarely changes (72h)
  variables: { ttl: 24 * 3600 }, // Tokens updated daily (24h)
  screenshots: { ttl: 6 * 3600 }, // Visual assets change frequently (6h)
  components: { ttl: 48 * 3600 } // Component structure stable (48h)
};

// Implementation
const cache = new Map();

async function getWithCache(key: string, fetcher: () => Promise<any>, ttl: number) {
  const cached = cache.get(key);
  const now = Date.now();

  if (cached && (now - cached.timestamp) < (ttl * 1000)) {
    console.log(`Cache hit for ${key}`);
    return cached.value;
  }

  const value = await fetcher();
  cache.set(key, { value, timestamp: now });
  return value;
}

// Usage
const variables = await getWithCache(
  `variables:abc123`,
  () => mcp__figma__get_variable_defs({fileId: "abc123"}),
  cacheConfig.variables.ttl
);
```

#### Batch Processing Optimization

```typescript
// Process components in optimal batch sizes (10-20 per batch)
async function exportComponentsBatch(
  nodeIds: string[],
  batchSize = 15
): Promise<any[]> {
  const results = [];

  for (let i = 0; i < nodeIds.length; i += batchSize) {
    const batch = nodeIds.slice(i, i + batchSize);

    // Parallel requests within batch
    const batchResults = await Promise.all(
      batch.map(nodeId =>
        mcp__figma__get_design_context({
          nodeId,
          clientLanguages: "typescript",
          dirForAssetWrites: "./src/generated"
        })
      )
    );

    results.push(...batchResults);

    // Small delay between batches to respect rate limits
    if (i + batchSize < nodeIds.length) {
      await new Promise(resolve => setTimeout(resolve, 100));
    }
  }

  return results;
}

// Usage: Export 150 components in 10 parallel requests
const allComponents = await exportComponentsBatch(
  Array.from({length: 150}, (_, i) => `component:${i}`)
);
```

---

## Level 4: Design System Integration Workflow

### Complete Design-to-Code Pipeline

```typescript
import * as fs from "fs";
import * as path from "path";

interface DesignSystemConfig {
  figmaFileId: string;
  figmaTeamId?: string;
  outputDir: string;
  componentNodeIds: string[];
  clientLanguages: "typescript" | "javascript";
}

async function syncDesignSystem(config: DesignSystemConfig) {
  const {figmaFileId, outputDir, componentNodeIds, clientLanguages} = config;

  console.log(`Starting design system sync for ${componentNodeIds.length} components...`);

  // Phase 1: Extract design tokens
  console.log("Phase 1: Extracting design tokens...");
  const variables = await mcp__figma__get_variable_defs({
    fileId: figmaFileId,
    teamId: config.figmaTeamId
  });

  const tokensOutput = path.join(outputDir, "tokens.json");
  fs.writeFileSync(tokensOutput, JSON.stringify(variables, null, 2));
  console.log(`✓ Tokens exported to ${tokensOutput}`);

  // Phase 2: Generate component code (parallel batch processing)
  console.log("Phase 2: Generating component code...");
  const components = await exportComponentsBatch(componentNodeIds, 15);

  const componentsDir = path.join(outputDir, "components");
  fs.mkdirSync(componentsDir, {recursive: true});

  components.forEach((component, index) => {
    const componentFile = path.join(
      componentsDir,
      `${component.componentName || `Component-${index}`}.ts`
    );
    fs.writeFileSync(componentFile, component.generatedCode || "");
  });

  console.log(`✓ Generated ${components.length} components`);

  // Phase 3: Export visual assets (parallel)
  console.log("Phase 3: Exporting visual assets...");
  const screenshots = await Promise.all(
    componentNodeIds.slice(0, 10).map(nodeId => // Limit to 10 for performance
      mcp__figma__get_screenshot({
        nodeId,
        format: "png",
        scale: 2
      })
    )
  );

  const assetsDir = path.join(outputDir, "assets");
  fs.mkdirSync(assetsDir, {recursive: true});

  screenshots.forEach((screenshot, index) => {
    const assetFile = path.join(assetsDir, `component-${index}.png`);
    fs.writeFileSync(assetFile, screenshot.imageData);
  });

  console.log(`✓ Exported ${screenshots.length} component previews`);

  // Phase 4: Generate documentation
  console.log("Phase 4: Generating documentation...");
  const docMarkdown = generateComponentDocs(components, variables);
  const docsFile = path.join(outputDir, "COMPONENTS.md");
  fs.writeFileSync(docsFile, docMarkdown);

  console.log(`✓ Documentation generated at ${docsFile}`);
  console.log(`\nDesign system sync complete!`);
  console.log(`Output directory: ${outputDir}`);
}

// Helper function
function generateComponentDocs(components: any[], tokens: any[]): string {
  let md = "# Auto-Generated Component Documentation\n\n";
  md += `Generated: ${new Date().toISOString()}\n\n`;

  md += "## Design Tokens\n\n";
  tokens.forEach(token => {
    md += `- \`${token.name}\`: ${token.value}\n`;
  });

  md += "\n## Components\n\n";
  components.forEach((comp, i) => {
    md += `### ${comp.componentName || `Component ${i}`}\n`;
    md += `Path: \`${comp.nodePath}\`\n`;
    md += "```typescript\n";
    md += comp.generatedCode?.substring(0, 200) + "...\n";
    md += "```\n\n";
  });

  return md;
}
```

---

## Design Token Management

### Token Extraction & Export

```typescript
// Extract tokens from Figma and export to multiple formats
async function exportTokens(figmaFileId: string, outputDir: string) {
  const variables = await mcp__figma__get_variable_defs({
    fileId: figmaFileId
  });

  // Format 1: CSS Custom Properties
  let cssContent = ":root {\n";
  variables.forEach(token => {
    cssContent += `  --${token.name}: ${token.value};\n`;
  });
  cssContent += "}\n";
  fs.writeFileSync(path.join(outputDir, "tokens.css"), cssContent);

  // Format 2: JSON (for JavaScript)
  const jsonTokens = Object.fromEntries(
    variables.map(token => [token.name, token.value])
  );
  fs.writeFileSync(
    path.join(outputDir, "tokens.json"),
    JSON.stringify(jsonTokens, null, 2)
  );

  // Format 3: SCSS Variables
  let scssContent = "";
  variables.forEach(token => {
    scssContent += `$${token.name}: ${token.value};\n`;
  });
  fs.writeFileSync(path.join(outputDir, "tokens.scss"), scssContent);

  console.log(`✓ Exported ${variables.length} tokens in 3 formats`);
}
```

---

## References

- **Figma API Documentation**: https://www.figma.com/developers
- **Figma REST API**: https://www.figma.com/developers/api
- **MCP Figma Integration**: https://github.com/anthropic-ai/mcp-server-figma
- **Design Tokens**: https://design-tokens.github.io/
- **Design System Best Practices**: https://www.designsystems.com/

---

**Last Updated**: 2025-11-19
**Format**: Markdown | **Language**: English
**Status**: Stable (v4.1.0)
**Version**: 4.1.0

### Changelog

**v4.1.0** (2025-11-19)
- Added MCP tool invocation patterns (sequential, parallel, conditional)
- Comprehensive error handling guide with solutions
- Performance optimization strategies (caching, batch processing)
- Parameter validation and auto-detection examples
- Complete design-to-code pipeline workflow
- Rate limiting and retry strategy documentation
- Token extraction and multi-format export examples
- Performance improvement metrics (20-70% speedup for parallel calls)

**v4.0.0** (2025-11-18)
- Initial stable release
- Core design system patterns
- Basic Figma API overview

