MCPInstall

figma-design-md-plugin

Figma plugin that extracts local styles and generates DESIGN.md and SKILL.md files for AI-driven design system implementation

Installs
119
Last 24h
—
Trending rank
—
Security
Not audited

Install

Works with every agent the skills CLI supports.

npx skills add https://github.com/reason-machines/design-skills --skill figma-design-md-plugin
  1. 01

    Install

    Run the command in your project. The CLI asks which agents to install for.

  2. 02

    Describe the task

    Ask your agent for something this skill covers. It loads figma-design-md-plugin automatically when relevant.

  3. 03

    Review the result

    The agent follows the SKILL.md steps, scripts and references bundled with the skill.

SKILL.md

The instructions your agent reads when the skill is triggered.

Figma Design.md Plugin Skill

Skill by ara.so — Design Skills collection.

Overview

The design-md-figma plugin extracts local styles, variables, and component families from Figma files and generates standardized DESIGN.md and SKILL.md files. These outputs provide AI coding agents with design-system blueprints for building consistent interfaces.

The plugin reads:

  • Local color/typography/spacing/radius/motion styles
  • Figma variable collections
  • Effect styles (shadows, blur)
  • Grid styles
  • Component families

It generates TypeUI-format markdown that AI agents can use to implement design-consistent code.

Installation & Setup

Development Setup

# Clone the repository
git clone https://github.com/bergside/design-md-figma.git
cd design-md-figma

# Install dependencies
npm install

# Build the plugin
npm run build

Load in Figma Desktop

  1. Open Figma Desktop
  2. Navigate to Plugins → Development → Import plugin from manifest...
  3. Select the manifest.json file from your cloned directory
  4. The plugin appears in Plugins → Development → Design MD Skill Generator

Watch Mode for Development

# Auto-rebuild on file changes
npm run watch

Plugin Architecture

File Structure

design-md-figma/
├── src/
│   ├── code.ts          # Main plugin logic (runs in Figma sandbox)
│   ├── ui.html          # Plugin UI (runs in iframe)
│   └── types.ts         # TypeScript type definitions
├── manifest.json        # Figma plugin configuration
└── package.json

Key TypeScript Interfaces

interface ExtractedData {
  source: {
    fileName: string;
    pageNames: string[];
    timestamp: string;
  };
  variableCollections: VariableCollection[];
  colorTokens: ColorToken[];
  typographyTokens: TypographyToken[];
  spacingTokens: SpacingToken[];
  radiusTokens: RadiusToken[];
  effectStyles: EffectStyle[];
  gridStyles: GridStyle[];
  componentFamilies: string[];
}

interface ColorToken {
  name: string;
  value: string; // hex, rgb(), or variable reference
  type: 'paint-style' | 'color-variable';
}

interface TypographyToken {
  name: string;
  fontFamily: string;
  fontSize: number;
  fontWeight: number;
  lineHeight: string;
  letterSpacing: string;
}

Core Plugin Functions

Extracting Design Tokens

The plugin automatically extracts tokens when run:

// Main extraction flow (src/code.ts)
async function extractDesignTokens(): Promise<ExtractedData> {
  const data: ExtractedData = {
    source: {
      fileName: figma.root.name,
      pageNames: figma.root.children.map(page => page.name),
      timestamp: new Date().toISOString()
    },
    variableCollections: [],
    colorTokens: [],
    typographyTokens: [],
    spacingTokens: [],
    radiusTokens: [],
    effectStyles: [],
    gridStyles: [],
    componentFamilies: []
  };

  // Extract local paint styles
  const paintStyles = figma.getLocalPaintStyles();
  paintStyles.forEach(style => {
    const paint = style.paints[0];
    if (paint.type === 'SOLID') {
      data.colorTokens.push({
        name: style.name,
        value: rgbToHex(paint.color),
        type: 'paint-style'
      });
    }
  });

  // Extract local text styles
  const textStyles = figma.getLocalTextStyles();
  textStyles.forEach(style => {
    data.typographyTokens.push({
      name: style.name,
      fontFamily: style.fontName.family,
      fontSize: style.fontSize,
      fontWeight: style.fontName.style,
      lineHeight: formatLineHeight(style.lineHeight),
      letterSpacing: formatLetterSpacing(style.letterSpacing)
    });
  });

  // Extract variable collections
  const collections = figma.variables.getLocalVariableCollections();
  collections.forEach(collection => {
    data.variableCollections.push({
      id: collection.id,
      name: collection.name,
      modes: collection.modes.map(m => m.name)
    });
  });

  return data;
}

Generating DESIGN.md

function generateDesignMD(data: ExtractedData): string {
  let markdown = `# DESIGN.md\n\n`;
  
  markdown += `## Source\n\n`;
  markdown += `- **File**: ${data.source.fileName}\n`;
  markdown += `- **Pages**: ${data.source.pageNames.join(', ')}\n`;
  markdown += `- **Extracted**: ${data.source.timestamp}\n\n`;

  markdown += `## Color Tokens\n\n`;
  markdown += `| Name | Value | Type |\n`;
  markdown += `| --- | --- | --- |\n`;
  data.colorTokens.forEach(token => {
    markdown += `| ${token.name} | ${token.value} | ${token.type} |\n`;
  });
  markdown += `\n`;

  markdown += `## Typography Tokens\n\n`;
  markdown += `| Name | Family | Size | Weight | Line Height | Letter Spacing |\n`;
  markdown += `| --- | --- | --- | --- | --- | --- |\n`;
  data.typographyTokens.forEach(token => {
    markdown += `| ${token.name} | ${token.fontFamily} | ${token.fontSize}px | ${token.fontWeight} | ${token.lineHeight} | ${token.letterSpacing} |\n`;
  });

  return markdown;
}

Generating SKILL.md

function generateSkillMD(data: ExtractedData): string {
  let markdown = `# SKILL.md\n\n`;
  
  markdown += `## Mission\n\n`;
  markdown += `Build interfaces that strictly adhere to the design system extracted from **${data.source.fileName}**.\n\n`;

  markdown += `## Style Foundations\n\n`;
  markdown += `### Colors\n\n`;
  data.colorTokens.forEach(token => {
    markdown += `- **${token.name}**: \`${token.value}\`\n`;
  });
  markdown += `\n`;

  markdown += `### Typography\n\n`;
  data.typographyTokens.forEach(token => {
    markdown += `- **${token.name}**: ${token.fontFamily} ${token.fontSize}px/${token.lineHeight}, weight ${token.fontWeight}\n`;
  });

  markdown += `\n## Rules: Do\n\n`;
  markdown += `- Use extracted color tokens exactly as defined\n`;
  markdown += `- Apply typography scales from text styles\n`;
  markdown += `- Reference component families for consistency\n`;
  markdown += `- Follow spacing/radius token values\n\n`;

  markdown += `## Rules: Don't\n\n`;
  markdown += `- Never hardcode colors outside extracted palette\n`;
  markdown += `- Don't create arbitrary font sizes\n`;
  markdown += `- Avoid inconsistent spacing values\n`;

  return markdown;
}

Message Passing (UI ↔ Plugin)

The plugin uses Figma's message API:

// In code.ts (plugin sandbox)
figma.ui.onmessage = async (msg) => {
  if (msg.type === 'extract') {
    const data = await extractDesignTokens();
    figma.ui.postMessage({
      type: 'extraction-complete',
      data
    });
  }
  
  if (msg.type === 'generate-design-md') {
    const markdown = generateDesignMD(msg.data);
    figma.ui.postMessage({
      type: 'markdown-ready',
      markdown,
      fileType: 'DESIGN.md'
    });
  }
};

// In ui.html (iframe)
window.onmessage = (event) => {
  const msg = event.data.pluginMessage;
  if (msg.type === 'extraction-complete') {
    displayExtractedData(msg.data);
  }
  if (msg.type === 'markdown-ready') {
    updateEditor(msg.markdown);
    enableDownload(msg.markdown, msg.fileType);
  }
};

Common Usage Patterns

Extract and Download DESIGN.md

// User opens plugin in Figma
// Plugin auto-extracts on load
figma.showUI(__html__, { width: 600, height: 800 });

const data = await extractDesignTokens();
figma.ui.postMessage({ type: 'extraction-complete', data });

// User clicks "Generate DESIGN.md"
// UI sends message to plugin
parent.postMessage({
  pluginMessage: { type: 'generate-design-md', data }
}, '*');

// Plugin generates markdown and sends back
const markdown = generateDesignMD(data);
figma.ui.postMessage({ 
  type: 'markdown-ready', 
  markdown, 
  fileType: 'DESIGN.md' 
});

// UI enables download button
function downloadFile(content: string, filename: string) {
  const blob = new Blob([content], { type: 'text/markdown' });
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = filename;
  a.click();
}

Refresh Token Extraction

// User modifies Figma file (adds new color style)
// User clicks "Refresh" in plugin UI
parent.postMessage({
  pluginMessage: { type: 'refresh' }
}, '*');

// Plugin re-runs extraction
const updatedData = await extractDesignTokens();
figma.ui.postMessage({ 
  type: 'extraction-complete', 
  data: updatedData 
});

Toggle Between DESIGN.md and SKILL.md

// UI state management
let currentView: 'design' | 'skill' = 'design';

function toggleView() {
  currentView = currentView === 'design' ? 'skill' : 'design';
  
  parent.postMessage({
    pluginMessage: { 
      type: currentView === 'design' ? 'generate-design-md' : 'generate-skill-md',
      data: extractedData
    }
  }, '*');
}

Configuration

manifest.json

{
  "name": "Design MD Skill Generator",
  "id": "1612814320994608244",
  "api": "1.0.0",
  "main": "dist/code.js",
  "ui": "dist/ui.html",
  "editorType": ["figma"],
  "networkAccess": {
    "allowedDomains": ["none"]
  }
}

TypeScript Configuration

{
  "compilerOptions": {
    "target": "ES6",
    "module": "commonjs",
    "lib": ["ES2015"],
    "outDir": "./dist",
    "strict": true,
    "typeRoots": ["./node_modules/@types", "./node_modules/@figma"]
  }
}

Helper Utilities

Color Conversion

function rgbToHex(color: RGB): string {
  const r = Math.round(color.r * 255).toString(16).padStart(2, '0');
  const g = Math.round(color.g * 255).toString(16).padStart(2, '0');
  const b = Math.round(color.b * 255).toString(16).padStart(2, '0');
  return `#${r}${g}${b}`;
}

function rgbaToString(color: RGBA): string {
  const r = Math.round(color.r * 255);
  const g = Math.round(color.g * 255);
  const b = Math.round(color.b * 255);
  return `rgba(${r}, ${g}, ${b}, ${color.a})`;
}

Typography Formatting

function formatLineHeight(lineHeight: LineHeight): string {
  if (lineHeight.unit === 'PIXELS') {
    return `${lineHeight.value}px`;
  }
  if (lineHeight.unit === 'PERCENT') {
    return `${lineHeight.value}%`;
  }
  return 'auto';
}

function formatLetterSpacing(spacing: LetterSpacing): string {
  if (spacing.unit === 'PIXELS') {
    return `${spacing.value}px`;
  }
  if (spacing.unit === 'PERCENT') {
    return `${spacing.value}%`;
  }
  return 'normal';
}

Component Family Detection

function extractComponentFamilies(): string[] {
  const families = new Set<string>();
  
  const components = figma.root.findAll(node => 
    node.type === 'COMPONENT_SET'
  ) as ComponentSetNode[];
  
  components.forEach(componentSet => {
    // Component set name format: "Button"
    families.add(componentSet.name);
  });
  
  return Array.from(families).sort();
}

Troubleshooting

Plugin Won't Load

Issue: Plugin doesn't appear in Figma menu

Solution:

# Ensure build completed successfully
npm run build

# Check dist/ folder exists with code.js and ui.html
ls -la dist/

# Verify manifest.json points to correct paths
cat manifest.json

No Styles Extracted

Issue: Generated markdown shows empty token lists

Solution:

  • Ensure file has local styles (not from external libraries)
  • Check Figma file has published color/text styles
  • Run Refresh after adding new styles
// Debug: Log style counts
console.log('Paint styles:', figma.getLocalPaintStyles().length);
console.log('Text styles:', figma.getLocalTextStyles().length);
console.log('Effect styles:', figma.getLocalEffectStyles().length);

Variable Collections Not Found

Issue: Variable collections section empty in DESIGN.md

Solution:

// Ensure using Figma API 1.0.0+ (supports variables)
const collections = figma.variables.getLocalVariableCollections();
if (collections.length === 0) {
  console.warn('No local variable collections found');
}

// Check file actually has variables defined
// Variables → View local variables in Figma

TypeScript Errors

Issue: Build fails with type errors

Solution:

# Install Figma type definitions
npm install --save-dev @figma/plugin-typings

# Run type check separately
npm run typecheck

# Common fix: ensure tsconfig includes Figma types
# tsconfig.json
{
  "compilerOptions": {
    "typeRoots": ["./node_modules/@types", "./node_modules/@figma"]
  }
}

Download Not Working

Issue: Download button doesn't trigger file save

Solution:

// Ensure blob creation and download logic is correct
function downloadMarkdown(content: string, filename: string) {
  const blob = new Blob([content], { type: 'text/markdown;charset=utf-8' });
  const url = URL.createObjectURL(blob);
  const link = document.createElement('a');
  link.href = url;
  link.download = filename;
  document.body.appendChild(link); // Required for Firefox
  link.click();
  document.body.removeChild(link);
  URL.revokeObjectURL(url); // Clean up
}

Integration with AI Agents

Using Generated DESIGN.md with Claude Code

# Add to project root
cp ~/Downloads/DESIGN.md ./DESIGN.md

# Reference in .claude/instructions
echo "Follow design tokens and guidelines in DESIGN.md" >> .claude/instructions

Using SKILL.md with Cursor

# Add to .cursor/ directory
mkdir -p .cursor
cp ~/Downloads/SKILL.md .cursor/design-system.md

# Cursor automatically reads skills from .cursor/

Programmatic Usage

import fs from 'fs';

// Read generated DESIGN.md
const designMD = fs.readFileSync('./DESIGN.md', 'utf-8');

// Parse color tokens (example)
const colorSection = designMD.match(/## Color Tokens\n\n([\s\S]*?)\n\n##/);
if (colorSection) {
  const rows = colorSection[1].split('\n').slice(2); // Skip header
  const colors = rows.map(row => {
    const [name, value, type] = row.split('|').map(s => s.trim());
    return { name, value, type };
  });
  console.log(colors);
}

Best Practices

  1. Run extraction on design-complete files — Extract after design system is stable
  2. Use local styles, not library styles — Plugin only reads local file styles
  3. Name styles consistently — Use hierarchical naming: color/primary/500, text/heading/h1
  4. Leverage variable collections — Map design tokens to Figma variables for better extraction
  5. Refresh after changes — Re-run extraction when styles/variables updated
  6. Commit generated files to repo — Keep DESIGN.md and SKILL.md in version control alongside code

TypeUI Format Compliance

Generated files follow TypeUI DESIGN.md specification:

  • Structured sections (Source, Tokens, Styles, Components)
  • Markdown tables for token lists
  • ISO 8601 timestamps
  • Hex color format for paint styles
  • Pixel-based sizing units
  • Component family enumeration

Resources

FAQ

What does the figma-design-md-plugin skill do?

Figma plugin that extracts local styles and generates DESIGN.md and SKILL.md files for AI-driven design system implementation

How do I install figma-design-md-plugin?

Run npx skills add https://github.com/reason-machines/design-skills --skill figma-design-md-plugin in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/figma-design-md-plugin/ (personal) or .claude/skills/figma-design-md-plugin/ (project).

Which AI agents can use figma-design-md-plugin?

Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.

Is figma-design-md-plugin safe to install?

No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.

Who maintains figma-design-md-plugin?

It is published by reason-machines in reason-machines/design-skills. It has 119 recorded installs.

More from reason-machines/design-skills

View all →

awesome-claude-design

reason-machines/design-skills

Open the skill to read its SKILL.md instructions.

205 installs

open-design-ai-prototyping

reason-machines/design-skills

Open the skill to read its SKILL.md instructions.

174 installs

design-md-format

reason-machines/design-skills

Open the skill to read its SKILL.md instructions.

171 installs

open-codesign-ai-design

reason-machines/design-skills

Open the skill to read its SKILL.md instructions.

171 installs

design-md-chrome-extractor

reason-machines/design-skills

Open the skill to read its SKILL.md instructions.

166 installs

claude-design-system-hooks

reason-machines/design-skills

Open the skill to read its SKILL.md instructions.

Frontend & Design165 installs

Popular frontend & design skills

View category →

setup-matt-pocock-skills

mattpocock/skills

Configure this repo for the engineering skills: set up its issue tracker, triage label vocabulary, and domain doc layout. Run once before first use of the other engineering skills.

Frontend & Design1.1M installs

frontend-design

anthropics/skills

Guidance for distinctive, intentional visual design when building new UI or reshaping an existing one. Helps with aesthetic direction, typography, and making choices that don't read as templated defaults.

OfficialFrontend & Design1M installs

hyperframes-animation

heygen-com/hyperframes

All animation knowledge for HyperFrames — atomic motion rules, multi-phase scene blueprints, scene transitions, broader motion-design techniques, AND the seven runtime adapters (GSAP default, plus Lottie, Three.js, Anime.js, CSS keyframes, Web Animations API, TypeGPU). Use for any motion or animation task: pick 2-4 rules and compose, or load a blueprint, or look up runtime-specific API (e.g. GSAP eases / Lottie player / Three.js mixer). Also covers auditing an existing composition's choreography (animation map) and 24 named text-animation effects. HyperFrames-native: single paused timeline, seek-safe, deterministic.

prototype

mattpocock/skills

Build a throwaway prototype to answer a design question. Use when the user wants to sanity-check whether a state model or logic feels right, or explore what a UI should look like.

Frontend & Design999.2K installs

hyperframes-core

heygen-com/hyperframes

The HyperFrames composition contract — build one renderable project. Use for composition structure, the data- timing attributes, class="clip", tracks, sub-compositions, variables, framework-owned media playback, deterministic-render rules, and validation. Read before writing composition HTML.

Frontend & Design930.5K installs

vercel-react-best-practices

vercel-labs/agent-skills

React and Next.js performance optimization guidelines from Vercel Engineering. This skill should be used when writing, reviewing, or refactoring React/Next.js code to ensure optimal performance patterns. Triggers on tasks involving React components, Next.js pages, data fetching, bundle optimization, or performance improvements.

OfficialFrontend & Design843.1K installs