MCPInstall

figma-capture-extension

Chrome extension that captures webpages into Figma's clipboard format with font fixes and DOM cleanup

Installs
122
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-capture-extension
  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-capture-extension 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 Capture Extension

Skill by ara.so — Design Skills collection

This Chrome extension captures any webpage into Figma's clipboard format, adding post-processing to fix fonts (especially CJK), clean up DOM structure, and remove empty elements before pasting into Figma.

What It Does

  • CJK Font Correction: Detects Chinese/Japanese/Korean text and remaps to PingFang SC / Noto Serif SC
  • Font Mapping: Remaps unavailable fonts via configurable font-map.json
  • Default Font Fallback: Assigns Noto Sans SC to elements without explicit fonts
  • DOM Flattening: Removes wrapper elements that don't contribute visually
  • Empty Frame Cleanup: Strips zero-size elements and childless containers
  • Event Isolation: Prevents toolbar clicks from affecting host page behavior

Installation

Step 1: Download Figma's Capture Script

make

This downloads capture.js from Figma's public endpoint. The Makefile does:

capture.js:
	curl -o capture.js https://www.figma.com/community/plugin/1159123024924461424/capture.js

Step 2: Configure Font Mapping

cp font-map.example.json font-map.json

Example font-map.json structure:

{
  "Arial": "Inter",
  "Helvetica": "Inter",
  "SF Pro Display": "Google Sans Flex",
  "Roboto": "Noto Sans SC",
  "system-ui": "Inter"
}

Step 3: Load Extension in Chrome

  1. Navigate to chrome://extensions
  2. Enable Developer mode (top right toggle)
  3. Click Load unpacked
  4. Select the figma-capture directory

Usage

Basic Capture Workflow

  1. Navigate to the webpage you want to capture
  2. Click the extension icon or press Alt+Shift+F
  3. Use the toolbar to:
    • Capture entire page
    • Select specific element by clicking
  4. Switch to Figma
  5. Press Ctrl+V (Windows) or Cmd+V (Mac)

Keyboard Shortcut

Default: Alt+Shift+F

To customize, go to chrome://extensions/shortcuts

Configuration Files

manifest.json

Key configuration sections:

{
  "manifest_version": 3,
  "name": "Figma Capture",
  "version": "1.0.0",
  "permissions": [
    "activeTab",
    "clipboardWrite"
  ],
  "background": {
    "service_worker": "background.js"
  },
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["content.js"],
      "run_at": "document_start"
    }
  ],
  "action": {
    "default_icon": "icon.png"
  },
  "commands": {
    "_execute_action": {
      "suggested_key": {
        "default": "Alt+Shift+F"
      }
    }
  }
}

Font Mapping Configuration

Edit font-map.json to add custom font substitutions:

{
  "SegoeUI": "Inter",
  "San Francisco": "Google Sans Flex",
  "PingFang": "PingFang SC",
  "Microsoft YaHei": "Noto Sans SC",
  "Hiragino Sans": "Noto Sans JP"
}

Font mapping logic (applied in order):

  1. CJK detection → PingFang SC / Noto Serif SC
  2. Custom font-map.json mappings
  3. Icon font detection → preserve original
  4. No font specified → Noto Sans SC

Architecture

Component Flow

User clicks extension icon
    ↓
background.js activates content script
    ↓
content.js injects capture.js
    ↓
capture.js serializes DOM → clipboard payload
    ↓
Clipboard interceptor transforms payload:
  - Font correction
  - DOM cleanup
  - Wrapper flattening
    ↓
Modified payload written to clipboard
    ↓
User pastes into Figma

Key Files

  • background.js: Service worker, patches attachShadow for event isolation
  • content.js: Injected script, intercepts clipboard API
  • capture.js: Figma's official serializer (downloaded, not in repo)
  • font-map.json: User-configurable font substitutions

Code Examples

Clipboard Interception Pattern

// Override clipboard write to transform Figma payload
const originalWrite = navigator.clipboard.write;
navigator.clipboard.write = async function(data) {
  const items = await Promise.all(data.map(async item => {
    if (item.types.includes('text/html')) {
      const blob = await item.getType('text/html');
      const html = await blob.text();
      
      // Transform Figma's clipboard payload
      const transformed = transformFigmaPayload(html);
      
      return new ClipboardItem({
        'text/html': new Blob([transformed], { type: 'text/html' })
      });
    }
    return item;
  }));
  
  return originalWrite.call(this, items);
};

Font Detection and Remapping

function detectAndFixFont(element, computedStyle) {
  const text = element.textContent || '';
  const fontFamily = computedStyle.fontFamily;
  
  // CJK detection
  const cjkRegex = /[\u4E00-\u9FFF\u3040-\u309F\u30A0-\u30FF\uAC00-\uD7AF]/;
  if (cjkRegex.test(text)) {
    // Check if serif
    const isSerif = /serif/i.test(fontFamily);
    return isSerif ? 'Noto Serif SC' : 'PingFang SC';
  }
  
  // Load font map
  const fontMap = loadFontMap(); // from font-map.json
  
  // Check for mapped font
  for (const [original, replacement] of Object.entries(fontMap)) {
    if (fontFamily.includes(original)) {
      return replacement;
    }
  }
  
  // Icon font detection (preserve)
  if (/icon|symbol|awesome|material/i.test(fontFamily)) {
    return fontFamily;
  }
  
  // Default fallback
  return fontFamily || 'Noto Sans SC';
}

DOM Cleanup: Wrapper Flattening

function flattenWrappers(node) {
  // Skip if not a wrapper candidate
  if (node.children.length !== 1) return false;
  
  const parent = node;
  const child = node.children[0];
  
  // Check if parent is just a pass-through container
  const parentStyle = getComputedStyle(parent);
  const childStyle = getComputedStyle(child);
  
  const isPassThrough = 
    parentStyle.backgroundColor === 'transparent' &&
    parentStyle.border === 'none' &&
    parent.getBoundingClientRect().width === child.getBoundingClientRect().width &&
    parent.getBoundingClientRect().height === child.getBoundingClientRect().height;
  
  if (isPassThrough) {
    // Promote child to parent's position
    parent.replaceWith(child);
    return true;
  }
  
  return false;
}

Event Isolation for Toolbar

// In background.js - save closed shadow roots
const shadowRoots = new WeakMap();

const originalAttachShadow = Element.prototype.attachShadow;
Element.prototype.attachShadow = function(init) {
  const shadowRoot = originalAttachShadow.call(this, init);
  if (init.mode === 'closed') {
    shadowRoots.set(this, shadowRoot);
  }
  return shadowRoot;
};

// In content.js - intercept toolbar clicks
window.addEventListener('click', (event) => {
  const toolbar = document.querySelector('.figma-capture-toolbar');
  if (!toolbar) return;
  
  const toolbarHost = toolbar.host;
  const shadowRoot = shadowRoots.get(toolbarHost);
  
  if (shadowRoot) {
    event.stopPropagation();
    event.preventDefault();
    
    // Re-dispatch inside shadow DOM
    const point = shadowRoot.elementFromPoint(event.clientX, event.clientY);
    if (point) {
      point.dispatchEvent(new MouseEvent('click', event));
    }
  }
}, true); // Capture phase

Common Patterns

Handling Special Elements

// Skip script/style/svg from processing
const SKIP_TAGS = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'LINK', 'META'];

function shouldProcessElement(element) {
  if (SKIP_TAGS.includes(element.tagName)) {
    return false;
  }
  
  // Skip hidden elements
  const style = getComputedStyle(element);
  if (style.display === 'none' || style.visibility === 'hidden') {
    return false;
  }
  
  // Skip zero-size elements
  const rect = element.getBoundingClientRect();
  if (rect.width === 0 && rect.height === 0) {
    return false;
  }
  
  return true;
}

Custom Font Mapping for Specific Websites

// Create site-specific font mappings
const siteSpecificMaps = {
  'github.com': {
    '-apple-system': 'Inter',
    'BlinkMacSystemFont': 'Inter',
    'Segoe UI': 'Inter'
  },
  'twitter.com': {
    'TwitterChirp': 'Google Sans Flex',
    'Helvetica Neue': 'Inter'
  }
};

function getFontMap() {
  const hostname = window.location.hostname;
  const baseMap = JSON.parse(localStorage.getItem('font-map.json') || '{}');
  const siteMap = siteSpecificMaps[hostname] || {};
  
  return { ...baseMap, ...siteMap };
}

Troubleshooting

Fonts Not Displaying Correctly in Figma

Problem: Pasted elements show default Times or incorrect fonts

Solution: Check if fonts are installed in Figma:

// Add debug logging to see what fonts are being applied
console.log('Applied font:', appliedFont);
console.log('Original font:', originalFont);
console.log('Font map:', fontMap);

Update font-map.json to map problematic fonts to fonts you have in Figma:

{
  "ProblematicFont": "Inter",
  "AnotherBadFont": "Roboto"
}

Extension Not Activating

Problem: Clicking icon does nothing

Solution: Check console for errors:

  1. Right-click extension icon → Inspect popup
  2. Go to chrome://extensions → Find Figma Capture → Click "background page"
  3. Check for errors in console

Verify capture.js exists:

ls -la capture.js
# If missing:
make

Clipboard Payload Not Modified

Problem: Fonts/cleanup not being applied

Solution: Verify clipboard interceptor is loaded:

// In browser console on target page:
console.log(navigator.clipboard.write.toString());
// Should show wrapped function, not native code

Reload extension:

  1. chrome://extensions
  2. Click reload icon for Figma Capture
  3. Refresh target webpage

Empty or Broken Capture

Problem: Pasting creates empty frame or errors

Solution: Some elements may be over-cleaned. Adjust cleanup logic:

// Disable wrapper flattening temporarily
const ENABLE_FLATTENING = false;

if (ENABLE_FLATTENING) {
  flattenWrappers(node);
}

Check for CSP violations in console — some sites block extension scripts.

CJK Text Not Detected

Problem: Chinese/Japanese/Korean text uses wrong font

Solution: Verify regex pattern matches your text:

const text = "你好世界";
const cjkRegex = /[\u4E00-\u9FFF\u3040-\u309F\u30A0-\u30FF\uAC00-\uD7AF]/;
console.log(cjkRegex.test(text)); // Should be true

Manually set font in font-map.json:

{
  "SimSun": "Noto Sans SC",
  "Microsoft YaHei": "PingFang SC"
}

Advanced Configuration

Modify Default Fallback Font

Edit content.js:

const DEFAULT_FALLBACK_FONT = 'Inter'; // Change from 'Noto Sans SC'

Add Custom Cleanup Rules

function customCleanup(element) {
  // Remove all data attributes
  for (const attr of element.attributes) {
    if (attr.name.startsWith('data-')) {
      element.removeAttribute(attr.name);
    }
  }
  
  // Remove specific classes
  const REMOVE_CLASSES = ['ad', 'banner', 'cookie-notice'];
  element.classList.remove(...REMOVE_CLASSES);
}

Debug Mode

Add to content.js:

const DEBUG = true;

function debug(...args) {
  if (DEBUG) {
    console.log('[Figma Capture]', ...args);
  }
}

debug('Font applied:', fontFamily);
debug('Element cleaned:', element.tagName);

Limitations

  • Figma Dependency: Relies on Figma's undocumented clipboard format (may break)
  • Font Availability: Target fonts must be installed in Figma
  • CSP Restrictions: Some sites block extension script injection
  • Dynamic Content: May not capture lazy-loaded or JavaScript-rendered elements
  • capture.js Updates: Figma may change/remove the download endpoint

Resources

FAQ

What does the figma-capture-extension skill do?

Chrome extension that captures webpages into Figma's clipboard format with font fixes and DOM cleanup

How do I install figma-capture-extension?

Run npx skills add https://github.com/reason-machines/design-skills --skill figma-capture-extension 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-capture-extension/ (personal) or .claude/skills/figma-capture-extension/ (project).

Which AI agents can use figma-capture-extension?

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-capture-extension 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-capture-extension?

It is published by reason-machines in reason-machines/design-skills. It has 122 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

design-md-format

reason-machines/design-skills

Create and validate DESIGN.md files that give AI coding agents structured understanding of design systems through machine-readable tokens and human-readable rationale.

178 installs

open-codesign-ai-design

reason-machines/design-skills

Use Open CoDesign to generate prototypes, slides, and PDFs from prompts with Claude, GPT, Gemini, or local models

AI & Agents175 installs

open-design-ai-prototyping

reason-machines/design-skills

Open the skill to read its SKILL.md instructions.

174 installs

diagram-design-editorial

reason-machines/design-skills

Create editorial-quality diagrams in HTML + SVG matching your brand — architecture, flowcharts, sequences, timelines, quadrants, and 9 more types.

Docs & Writing169 installs

claude-design-system-hooks

reason-machines/design-skills

AI-powered design-to-code engine that generates production-ready UI components from natural language using Claude API

Frontend & Design169 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