Skip to content
OpenSmartRoute
Skillv1.0.0

figma-core-workflow-a

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 syste

by jeremylongshore(0) 0 installs
Free
Sign in to install

Free account. Installing gives you the manifest plus copy-paste snippets.

See reviews

About

Imported from jeremylongshore/tons-of-skills-marketplace (plugins/saas-packs/figma-pack/skills/figma-core-workflow-a/SKILL.md). Install upstream with npx skills add jeremylongshore/tons-of-skills-marketplace --skill figma-core-workflow-a. Copyright stays with the author (MIT).

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

Error Cause Solution
Empty styles map File has no published styles Publish styles in Figma first
null node in response Node was deleted Filter nulls before processing
403 on variables endpoint Not Enterprise plan Use styles endpoint instead
Color looks wrong Forgot 0-1 to 0-255 conversion Multiply 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.

Use it

Copy one of these into your project. Installing also returns the manifest and these snippets.

yaml
targets:
  - https://api.opensmartroute.ai/api/v1/registry/jeremylongshore-tons-of-skills-marketplace-figma-core-wo-25c475/manifest   # or paste the manifest below

Manifest

An Open Capability Manifest: the router reads it to know what this does, what it costs and when to pick it.

jeremylongshore-tons-of-skills-marketplace-figma-core-wo-25c475.ocm.jsonjson
{
  "ocm": "1",
  "id": "jeremylongshore-tons-of-skills-marketplace-figma-core-wo-25c475",
  "kind": "skill",
  "name": "figma-core-workflow-a",
  "description": "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\".",
  "publisher": "jeremylongshore",
  "version": "1.0.0",
  "capabilities": {
    "domains": [
      "coding"
    ],
    "tags": [
      "skill-md",
      "saas",
      "figma",
      "skills-sh"
    ],
    "languages": [
      "en"
    ]
  },
  "quality_prior": 0.6,
  "examples": [
    "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\"."
  ],
  "primary": false,
  "metadata": {
    "source": {
      "provider": "skills.sh",
      "repository": "https://github.com/jeremylongshore/tons-of-skills-marketplace",
      "path": "plugins/saas-packs/figma-pack/skills/figma-core-workflow-a/SKILL.md",
      "ref": "HEAD",
      "url": "https://github.com/jeremylongshore/tons-of-skills-marketplace/blob/HEAD/plugins/saas-packs/figma-pack/skills/figma-core-workflow-a/SKILL.md",
      "key": "jeremylongshore/tons-of-skills-marketplace/plugins/saas-packs/figma-pack/skills/figma-core-workflow-a/SKILL.md"
    },
    "compatibility": "Designed for Claude Code",
    "allowed_tools": [
      "Read,",
      "Write,",
      "Edit,",
      "Bash(npm:*),",
      "Bash(node:*),",
      "Grep"
    ],
    "license": "MIT"
  },
  "instructions": "# Figma Core Workflow A -- Design Token Extraction\n\n## Overview\n\nThe 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.\n\n## Prerequisites\n\n- Completed `figma-install-auth` setup\n- A Figma file with published styles or variables\n- `FIGMA_PAT` and `FIGMA_FILE_KEY` env vars set\n\n## Instructions\n\n### Step 1: Fetch Styles from a File\n\n```typescript\nimport { FigmaClient } from './figma-client';\n\nconst client = new FigmaClient(process.env.FIGMA_PAT!);\nconst",
  "cost": {
    "context_tokens": 1677
  }
}

Fetch it by URL: GET /api/v1/registry/jeremylongshore-tons-of-skills-marketplace-figma-core-wo-25c475/manifest?version=1.0.0

Reviews

Star ratings from people who tried it. One review per account; edit yours any time.

No reviews yet. Install it, try it, and be the first to rate it.