figma-core-workflow-a

v2026.09.24

Extract design tokens, colors, typography, and spacing from Figma files via REST API. Use when building a design-to-code pipeline, syncing design tokens, or extracting styles from a Figma design system file. Trigger with phrases like "figma design tokens", "extract figma styles", "figma to CSS", "sync figma colors", "figma typography".

GitHub
安装命令
npx skhub add jeremylongshore/figma-core-workflow-a
Markdown
SKILL.md

Figma Core Workflow A -- Design Token Extraction

Overview

The primary workflow for Figma API integrations: extracting design tokens (colors, typography, spacing) from a Figma file and converting them to CSS custom properties, JSON tokens, or Tailwind config.

Prerequisites

  • Completed figma-install-auth setup
  • A Figma file with published styles or variables
  • FIGMA_PAT and FIGMA_FILE_KEY env vars set

Instructions

Step 1: Fetch Styles from a File

import { FigmaClient } from './figma-client';

const client = new FigmaClient(process.env.FIGMA_PAT!);
const fileKey = process.env.FIGMA_FILE_KEY!;

// GET /v1/files/:key -- returns styles map in response
const file = await client.getFile(fileKey);

// file.styles is a map: nodeId -> { key, name, style_type, description }
// style_type: "FILL" | "TEXT" | "EFFECT" | "GRID"
const colorStyles = Object.entries(file.styles)
  .filter(([, s]) => s.style_type === 'FILL')
  .map(([nodeId, s]) => ({ nodeId, name: s.name }));

const textStyles = Object.entries(file.styles)
  .filter(([, s]) => s.style_type === 'TEXT')
  .map(([nodeId, s]) => ({ nodeId, name: s.name }));

console.log(`Found ${colorStyles.length} color styles, ${textStyles.length} text styles`);

Step 2: Resolve Style Values from Nodes

// Fetch the actual nodes to get fill colors and text properties
const styleNodeIds = colorStyles.map(s => s.nodeId);
const nodesResponse = await client.getFileNodes(fileKey, styleNodeIds);

interface DesignToken {
  name: string;
  type: 'color' | 'typography' | 'spacing';
  value: string;
}

const tokens: DesignToken[] = [];

for (const [nodeId, nodeData] of Object.entries(nodesResponse.nodes)) {
  const node = nodeData.document;
  const styleName = colorStyles.find(s => s.nodeId === nodeId)?.name;

  if (node.fills?.[0]?.type === 'SOLID' && node.fills[0].color) {
    const { r, g, b, a } = node.fills[0].color;
    // Figma colors are 0-1 floats; convert to 0-255
    const hex = '#' + [r, g, b].map(v =>
      Math.round(v * 255).toString(16).padStart(2, '0')
    ).join('');

    tokens.push({
      name: styleName ?? node.name,
      type: 'color',
      value: a !== undefined && a < 1
        ? `rgba(${Math.round(r*255)}, ${Math.round(g*255)}, ${Math.round(b*255)}, ${a.toFixed(2)})`
        : hex,
    });
  }
}

Step 3: Extract Typography Tokens

// Fetch text style nodes
const textNodeIds = textStyles.map(s => s.nodeId);
const textNodes = await client.getFileNodes(fileKey, textNodeIds);

for (const [nodeId, nodeData] of Object.entries(textNodes.nodes)) {
  const node = nodeData.document;
  const styleName = textStyles.find(s => s.nodeId === nodeId)?.name;

  if (node.style) {
    tokens.push({
      name: styleName ?? node.name,
      type: 'typography',
      value: JSON.stringify({
        fontFamily: node.style.fontFamily,
        fontSize: `${node.style.fontSize}px`,
        fontWeight: node.style.fontWeight,
        lineHeight: node.style.lineHeightPx
          ? `${node.style.lineHeightPx}px`
          : 'normal',
        letterSpacing: node.style.letterSpacing
          ? `${node.style.letterSpacing}px`
          : '0',
      }),
    });
  }
}

Step 4: Generate CSS Custom Properties

function tokensToCss(tokens: DesignToken[]): string {
  const lines = [':root {'];
  for (const token of tokens) {
    const varName = `--${token.name.toLowerCase().replace(/[\s/]+/g, '-')}`;
    if (token.type === 'color') {
      lines.push(`  ${varName}: ${token.value};`);
    } else if (token.type === 'typography') {
      const t = JSON.parse(token.value);
      lines.push(`  ${varName}-family: ${t.fontFamily};`);
      lines.push(`  ${varName}-size: ${t.fontSize};`);
      lines.push(`  ${varName}-weight: ${t.fontWeight};`);
    }
  }
  lines.push('}');
  return lines.join('\n');
}

import { writeFileSync } from 'fs';
writeFileSync('src/styles/tokens.css', tokensToCss(tokens));
console.log(`Generated ${tokens.length} tokens to src/styles/tokens.css`);

Step 5: Use Variables API (Enterprise)

// GET /v1/files/:key/variables/local (Tier 2, requires file_variables:read)
const vars = await client.getLocalVariables(fileKey);

// vars.meta.variables: Record<variableId, Variable>
// vars.meta.variableCollections: Record<collectionId, Collection>
for (const [id, variable] of Object.entries(vars.meta.variables)) {
  const collection = vars.meta.variableCollections[variable.variableCollectionId];
  console.log(`${collection.name}/${variable.name}: ${variable.resolvedType}`);
  // resolvedType: "COLOR" | "FLOAT" | "STRING" | "BOOLEAN"

  // Each variable has values per mode
  for (const [modeId, value] of Object.entries(variable.valuesByMode)) {
    const modeName = collection.modes.find(m => m.modeId === modeId)?.name;
    console.log(`  ${modeName}: ${JSON.stringify(value)}`);
  }
}

Output

  • Design tokens extracted from Figma styles or variables
  • CSS custom properties file generated
  • Color values converted from Figma's 0-1 float format to hex/rgba
  • Typography properties mapped to CSS-compatible values

Error Handling

ErrorCauseSolution
Empty styles mapFile has no published stylesPublish styles in Figma first
null node in responseNode was deletedFilter nulls before processing
403 on variables endpointNot Enterprise planUse styles endpoint instead
Color looks wrongForgot 0-1 to 0-255 conversionMultiply by 255 before hex

Examples

Extract every fill color used by published styles and emit CSS custom properties:

# 1. List published styles, 2. resolve their node values (see Steps 1-2)
curl -s -H "X-Figma-Token: ${FIGMA_PAT}" \
  "https://api.figma.com/v1/files/${FIGMA_FILE_KEY}/styles" \
  | jq -r '.meta.styles[] | select(.style_type == "FILL") | "\(.node_id)\t\(.name)"'
1:5   Color/Brand/Primary
1:6   Color/Brand/Secondary
1:9   Color/Neutral/100

Feed those node IDs to /v1/files/:key/nodes?ids=... and run the Step 4 generator to produce:

:root {
  --color-brand-primary: #4f46e5;
  --color-brand-secondary: #22d3ee;
  --color-neutral-100: #f5f5f5;
}

Full token-extraction walkthrough: references/extract-typography-tokens.md and references/generate-css-custom-properties.md.

Resources

Next Steps

For asset export, see figma-core-workflow-b.

发现
标签

此技能尚未发布标签。

版本
最新版本元数据

版本

v2026.09.24

发布时间

2026年9月24日

分类

未分类

许可证

MIT

源路径

skills/.curated/figma-core-workflow-a

默认分支

main

最新提交

e5a6c3b

Tree SHA

c2dc8e8