| name | figma |
| description | Integrate with Figma API for design automation and code generation. Use when extracting design tokens, generating React/CSS code from Figma components, syncing design systems, building Figma plugins, or automating design-to-code workflows. Triggers on Figma API, design tokens, Figma plugin, design-to-code, Figma export, Figma component, Dev Mode. |
Figma API Integration
Extract design data, generate code from components, and automate design workflows with Figma's API.
Quick Start
Authentication
const FIGMA_TOKEN = process.env.FIGMA_TOKEN;
const headers = {
'X-Figma-Token': FIGMA_TOKEN
};
const response = await fetch(
`https://api.figma.com/v1/files/${FILE_KEY}`,
{ headers }
);
File Key & Node IDs
const figmaUrl = 'https://www.figma.com/file/abc123/MyDesign?node-id=1%3A2';
const fileKey = figmaUrl.match(/file\/([^/]+)/)?.[1];
const nodeId = new URL(figmaUrl).searchParams.get('node-id');
Core API Endpoints
Get File
GET https:
GET https:
GET https:
GET https:
Get Components
GET https:
GET https:
GET https:
Export Images
GET https:
GET https:
{
"images": {
"1:2": "https://s3.amazonaws.com/...",
"1:3": "https://s3.amazonaws.com/..."
}
}
Component Code Generation
Figma Node to React Component
interface FigmaNode {
id: string;
name: string;
type: string;
children?: FigmaNode[];
absoluteBoundingBox?: { x: number; y: number; width: number; height: number };
fills?: Fill[];
strokes?: Stroke[];
effects?: Effect[];
cornerRadius?: number;
paddingLeft?: number;
paddingRight?: number;
paddingTop?: number;
paddingBottom?: number;
itemSpacing?: number;
layoutMode?: 'HORIZONTAL' | 'VERTICAL' | 'NONE';
primaryAxisAlignItems?: string;
counterAxisAlignItems?: string;
characters?: string;
style?: TextStyle;
}
async function getComponentCode(fileKey: , : ): <> {
response = (
,
{ : { : process..! } }
);
data = response.();
node = data.[nodeId].;
(node);
}
(): {
componentName = (node.);
styles = (node);
children = node.?.( (child)).() || ;
;
}
(): . {
: . = {};
(node.) {
styles. = node..;
styles. = node..;
}
(node.?.) {
fill = node..( f. !== && f. === );
(fill?.) {
styles. = (fill.);
}
}
(node.) {
styles. = node.;
}
(node.) styles. = node.;
(node.) styles. = node.;
(node.) styles. = node.;
(node.) styles. = node.;
(node. && node. !== ) {
styles. = ;
styles. = node. === ? : ;
styles. = node.;
: <, > = {
: ,
: ,
: ,
: ,
};
(node.) {
styles. = alignMap[node.] || ;
}
(node.) {
styles. = alignMap[node.] || ;
}
}
styles;
}
(): {
styles = (node);
(node. === ) {
;
}
(node. === || node. === ) {
;
}
children = node.?.( (child)).() || ;
;
}
Generate Tailwind CSS from Figma
function figmaToTailwind(node: FigmaNode): string {
const classes: string[] = [];
if (node.absoluteBoundingBox) {
const { width, height } = node.absoluteBoundingBox;
classes.push(`w-[${Math.round(width)}px]`, `h-[${Math.round(height)}px]`);
}
if (node.fills?.length) {
const fill = node.fills.find(f => f.visible !== false && f.type === 'SOLID');
if (fill?.color) {
const hex = rgbaToHex(fill.color);
classes.push(`bg-[${hex}]`);
}
}
if (node.cornerRadius) {
const radiusMap: Record<number, string> = {
4: 'rounded-sm', : , : ,
: , : , :
};
classes.(radiusMap[node.] || );
}
(node. === node. &&
node. === node. &&
node. === node.) {
classes.();
} {
(node.) classes.();
(node.) classes.();
(node.) classes.();
(node.) classes.();
}
(node. && node. !== ) {
classes.();
classes.(node. === ? : );
(node.) classes.();
: <, > = {
: , : ,
: , :
};
: <, > = {
: , : , :
};
(node.) classes.(justifyMap[node.]);
(node.) classes.(alignMap[node.]);
}
classes.();
}
Extract All Components from File
interface ComponentInfo {
key: string;
name: string;
description: string;
nodeId: string;
thumbnailUrl?: string;
}
async function getAllComponents(fileKey: string): Promise<ComponentInfo[]> {
const response = await fetch(
`https://api.figma.com/v1/files/${fileKey}/components`,
{ headers: { 'X-Figma-Token': process.env.FIGMA_TOKEN! } }
);
const data = await response.json();
return data.meta.components.map((comp: any) => ({
key: comp.key,
name: comp.name,
description: comp.description || '',
nodeId: comp.node_id,
thumbnailUrl: comp.thumbnail_url,
}));
}
async (): <<, >> {
components = (fileKey);
codeMap = <, >();
( comp components) {
code = (fileKey, comp.);
codeMap.(comp., code);
}
codeMap;
}
Design Token Extraction
Extract Colors
async function extractColors(fileKey: string) {
const file = await fetch(
`https://api.figma.com/v1/files/${fileKey}/styles`,
{ headers }
).then(r => r.json());
const colors = {};
for (const style of file.meta.styles) {
if (style.style_type === 'FILL') {
const nodeData = await getStyleNode(fileKey, style.node_id);
const fill = nodeData.fills[0];
if (fill.type === 'SOLID') {
colors[style.name] = rgbaToHex(fill.color);
}
}
}
return colors;
}
function rgbaToHex({ r, g, b, a = 1 }) {
const toHex = (n) => Math.round(n * 255).toString(16).padStart(, );
;
}
Extract Typography Tokens
async function extractTypography(fileKey: string) {
const response = await fetch(
`https://api.figma.com/v1/files/${fileKey}/styles`,
{ headers: { 'X-Figma-Token': process.env.FIGMA_TOKEN! } }
);
const data = await response.json();
const typography: Record<string, any> = {};
for (const style of data.meta.styles) {
if (style.style_type === 'TEXT') {
const nodeResponse = await fetch(
`https://api.figma.com/v1/files/${fileKey}/nodes?ids=${style.node_id}`,
{ headers: { 'X-Figma-Token': process.env.FIGMA_TOKEN! } }
);
const nodeData = await nodeResponse.json();
const node = nodeData.nodes[style.node_id].document;
typography[style.name] = {
fontFamily: node.?.,
: node.?.,
: node.?.,
: node.?.,
: node.?.,
};
}
}
typography;
}
Generate Complete Design Tokens
interface DesignTokens {
colors: Record<string, string>;
typography: Record<string, any>;
spacing: Record<string, number>;
shadows: Record<string, string>;
radii: Record<string, number>;
}
async function generateDesignTokens(fileKey: string): Promise<DesignTokens> {
const [colors, typography] = await Promise.all([
extractColors(fileKey),
extractTypography(fileKey),
]);
return {
colors,
typography,
spacing: { xs: 4, sm: 8, md: 16, lg: 24, xl: 32 },
shadows: {},
radii: {},
};
}
(): {
css = ;
( [name, value] .(tokens.)) {
cssName = name.().(, );
css += ;
}
( [name, style] .(tokens.)) {
cssName = name.().(, );
css += ;
css += ;
css += ;
css += ;
}
css += ;
css;
}
(): {
: <, > = {};
( [name, value] .(tokens.)) {
key = name.().(, );
colors[key] = value;
}
;
}
Variables API (Design Tokens 2.0)
GET https:
GET https:
interface VariableCollection {
id: string;
name: string;
modes: { modeId: string; name: string }[];
variableIds: string[];
}
interface Variable {
id: string;
name: string;
resolvedType: 'BOOLEAN' | 'FLOAT' | 'STRING' | 'COLOR';
valuesByMode: Record<string, any>;
}
async function getVariables(fileKey: string) {
const response = await fetch(
`https://api.figma.com/v1/files/${fileKey}/variables/local`,
{ headers: { 'X-Figma-Token': process.env.! } }
);
response.();
}
Dev Mode Integration
Code Snippets from Dev Mode
GET https:
POST https:
{
"dev_resource": {
"name": "React Component",
"url": "https://github.com/...",
"file_key": "abc123",
"node_id": "1:2"
}
}
Webhooks
Setup Webhook
POST https:
{
"event_type": "FILE_UPDATE",
"team_id": "123456",
"endpoint": "https://your-server.com/figma-webhook",
"passcode": "your-secret-passcode"
}
Handle Webhook
app.post('/figma-webhook', async (req, res) => {
const { passcode } = req.body;
if (passcode !== process.env.FIGMA_WEBHOOK_SECRET) {
return res.status(401).send('Unauthorized');
}
const { event_type, file_key, timestamp } = req.body;
switch (event_type) {
case 'FILE_UPDATE':
await syncDesignTokens(file_key);
break;
case 'LIBRARY_PUBLISH':
await regenerateComponents(file_key);
break;
case 'FILE_COMMENT':
await notifyTeam(req.body);
break;
}
res.status(200).send('OK');
});
Complete Design-to-Code Pipeline
async function figmaToCode(fileKey: string, outputDir: string) {
const components = await getAllComponents(fileKey);
const tokens = await generateDesignTokens(fileKey);
await fs.writeFile(
`${outputDir}/tokens.css`,
tokensToCSSVariables(tokens)
);
await fs.writeFile(
`${outputDir}/tailwind.config.js`,
tokensToTailwindConfig(tokens)
);
for (const comp of components) {
const code = await getComponentCode(fileKey, comp.nodeId);
const fileName = toPascalCase(comp.name) + '.tsx';
await fs.writeFile(`${outputDir}/components/${fileName}`, code);
}
const icons = components.filter( => c..());
(icons.) {
iconIds = icons.( i.).();
svgResponse = (
,
{ : { : process..! } }
);
svgData = svgResponse.();
( icon icons) {
svgUrl = svgData.[icon.];
svg = (svgUrl).( r.());
fs.(, svg);
}
}
.();
}
Figma Plugin Development
Plugin Manifest (manifest.json)
{
"name": "My Figma Plugin",
"id": "123456789",
"api": "1.0.0",
"main": "code.js",
"ui": "ui.html",
"editorType": ["figma", "figjam"],
"capabilities": ["codegen"],
"codegenLanguages": [
{ "label": "React", "value": "react" },
{ "label": "Vue", "value": "vue" }
]
}
Plugin Code (code.ts)
figma.showUI(__html__, { width: 400, height: 500 });
figma.on('selectionchange', () => {
const selection = figma.currentPage.selection;
figma.ui.postMessage({ type: 'selection', nodes: selection.map(nodeToJSON) });
});
figma.ui.onmessage = async (msg) => {
if (msg.type === 'export-code') {
const node = figma.currentPage.selection[0];
const code = generateCode(node);
figma.ui.postMessage({ type: 'code-generated', code });
}
};
function nodeToJSON(node: SceneNode) {
return {
id: node.id,
name: node.name,
type: node.type,
width: node.width,
height: node.,
};
}
Resources