vibefigma-figma-to-react

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

VibeFigma - Figma to React Converter

VibeFigma - Figma转React转换器

Skill by ara.so — Design Skills collection.
VibeFigma is an open-source tool that transforms Figma designs into production-ready React components with Tailwind CSS. It uses the official Figma API to extract designs and generate clean, maintainable TypeScript/React code.
ara.so开发的技能工具 — 设计技能合集。
VibeFigma是一款开源工具,可将Figma设计转换为可用于生产环境的React组件(搭配Tailwind CSS)。它使用官方Figma API提取设计内容,并生成简洁、可维护的TypeScript/React代码。

Installation

安装

VibeFigma can be used without installation via npx, or installed globally/locally:
bash
undefined
VibeFigma可通过npx直接使用无需安装,也可全局或本地安装:
bash
undefined

Run directly (recommended)

直接运行(推荐)

npx vibefigma
npx vibefigma

Install globally

全局安装

npm install -g vibefigma
npm install -g vibefigma

Install as dev dependency

安装为开发依赖

npm install --save-dev vibefigma
undefined
npm install --save-dev vibefigma
undefined

Prerequisites

前置条件

You need a Figma Personal Access Token:
  1. Go to https://www.figma.com/settings
  2. Scroll to Personal Access Tokens
  3. Click Generate new token
  4. Copy the token and store it securely
Set the token as an environment variable:
bash
export FIGMA_TOKEN=your_figma_access_token
Or create a
.env
file:
env
FIGMA_TOKEN=your_figma_access_token
你需要一个Figma个人访问令牌:
  1. 访问https://www.figma.com/settings
  2. 滚动到Personal Access Tokens(个人访问令牌)部分
  3. 点击Generate new token(生成新令牌)
  4. 复制令牌并安全存储
将令牌设置为环境变量:
bash
export FIGMA_TOKEN=your_figma_access_token
或创建
.env
文件:
env
FIGMA_TOKEN=your_figma_access_token

CLI Usage

CLI使用方法

Interactive Mode (Easiest)

交互模式(最简单)

bash
npx vibefigma --interactive
The CLI will prompt you for:
  • Figma URL
  • Access token (if not in env)
  • Output paths
bash
npx vibefigma --interactive
CLI会提示你输入:
  • Figma链接
  • 访问令牌(如果未在环境变量中设置)
  • 输出路径

Direct Command

直接命令

bash
undefined
bash
undefined

Basic usage

基础用法

With explicit token

指定令牌

Custom output paths

自定义输出路径

npx vibefigma "https://www.figma.com/design/FILE_ID/FILE_NAME?node-id=NODE_ID"
--component ./src/components/Hero.tsx
--assets ./public/images
npx vibefigma "https://www.figma.com/design/FILE_ID/FILE_NAME?node-id=NODE_ID"
--component ./src/components/Hero.tsx
--assets ./public/images

Force overwrite without confirmation

强制覆盖无需确认

Common Options

常用选项

bash
undefined
bash
undefined

Disable Tailwind CSS (generate regular CSS)

禁用Tailwind CSS(生成常规CSS)

npx vibefigma [url] --no-tailwind
npx vibefigma [url] --no-tailwind

Optimize generated code

优化生成的代码

npx vibefigma [url] --optimize
npx vibefigma [url] --optimize

Use AI code cleaner (requires GOOGLE_GENERATIVE_AI_API_KEY)

使用AI代码清理工具(需要GOOGLE_GENERATIVE_AI_API_KEY)

npx vibefigma [url] --clean
npx vibefigma [url] --clean

Disable responsive design

禁用响应式设计

npx vibefigma [url] --no-responsive
npx vibefigma [url] --no-responsive

Don't include font imports

不包含字体导入

npx vibefigma [url] --no-fonts
npx vibefigma [url] --no-fonts

Disable absolute positioning

禁用绝对定位

npx vibefigma [url] --no-absolute
undefined
npx vibefigma [url] --no-absolute
undefined

Full CLI Options

完整CLI选项

Options:
  -V, --version                 Output version
  -t, --token <token>           Figma access token (overrides FIGMA_TOKEN)
  -u, --url <url>               Figma file/node URL
  -c, --component <path>        Component output path (default: ./src/components/[ComponentName].tsx)
  -a, --assets <dir>            Assets directory (default: ./public)
  --no-tailwind                 Disable Tailwind CSS
  --optimize                    Optimize components
  --clean                       Use AI code cleaner
  --no-classes                  Don't generate CSS classes
  --no-absolute                 Don't use absolute positioning
  --no-responsive               Disable responsive design
  --no-fonts                    Don't include fonts
  --interactive                 Force interactive mode
  -f, --force                   Overwrite existing files without confirmation
  -h, --help                    Display help
Options:
  -V, --version                 输出版本号
  -t, --token <token>           Figma访问令牌(覆盖FIGMA_TOKEN环境变量)
  -u, --url <url>               Figma文件/节点链接
  -c, --component <path>        组件输出路径(默认:./src/components/[ComponentName].tsx)
  -a, --assets <dir>            资源目录(默认:./public)
  --no-tailwind                 禁用Tailwind CSS
  --optimize                    优化组件
  --clean                       使用AI代码清理工具
  --no-classes                  不生成CSS类
  --no-absolute                 不使用绝对定位
  --no-responsive               禁用响应式设计
  --no-fonts                    不包含字体
  --interactive                 强制开启交互模式
  -f, --force                   无需确认直接覆盖现有文件
  -h, --help                    显示帮助信息

Real-World Examples

实际应用示例

Example 1: Convert Login Form

示例1:转换登录表单

bash
undefined
bash
undefined

Figma URL for a login form component

登录表单组件的Figma链接

npx vibefigma
"https://www.figma.com/design/4i8Tp5btFPRqtkYXplnfT6/50-Web-Sign-up-log-in-designs--Community-?node-id=26-2944"
--component ./src/components/LoginForm.tsx
--assets ./public/login-assets
--force

Generated output (example):

```typescript
// src/components/LoginForm.tsx
import React from 'react';

export const LoginForm: React.FC = () => {
  return (
    <div className="flex flex-col items-center justify-center min-h-screen bg-gray-50">
      <div className="w-full max-w-md p-8 space-y-6 bg-white rounded-lg shadow-md">
        <h2 className="text-2xl font-bold text-center text-gray-900">
          Sign In
        </h2>
        <form className="space-y-4">
          <div>
            <label htmlFor="email" className="block text-sm font-medium text-gray-700">
              Email
            </label>
            <input
              id="email"
              type="email"
              className="w-full px-3 py-2 mt-1 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
              placeholder="you@example.com"
            />
          </div>
          <div>
            <label htmlFor="password" className="block text-sm font-medium text-gray-700">
              Password
            </label>
            <input
              id="password"
              type="password"
              className="w-full px-3 py-2 mt-1 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
            />
          </div>
          <button
            type="submit"
            className="w-full px-4 py-2 text-white bg-blue-600 rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500"
          >
            Sign In
          </button>
        </form>
      </div>
    </div>
  );
};
npx vibefigma
"https://www.figma.com/design/4i8Tp5btFPRqtkYXplnfT6/50-Web-Sign-up-log-in-designs--Community-?node-id=26-2944"
--component ./src/components/LoginForm.tsx
--assets ./public/login-assets
--force

生成的输出示例:

```typescript
// src/components/LoginForm.tsx
import React from 'react';

export const LoginForm: React.FC = () => {
  return (
    <div className="flex flex-col items-center justify-center min-h-screen bg-gray-50">
      <div className="w-full max-w-md p-8 space-y-6 bg-white rounded-lg shadow-md">
        <h2 className="text-2xl font-bold text-center text-gray-900">
          Sign In
        </h2>
        <form className="space-y-4">
          <div>
            <label htmlFor="email" className="block text-sm font-medium text-gray-700">
              Email
            </label>
            <input
              id="email"
              type="email"
              className="w-full px-3 py-2 mt-1 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
              placeholder="you@example.com"
            />
          </div>
          <div>
            <label htmlFor="password" className="block text-sm font-medium text-gray-700">
              Password
            </label>
            <input
              id="password"
              type="password"
              className="w-full px-3 py-2 mt-1 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
            />
          </div>
          <button
            type="submit"
            className="w-full px-4 py-2 text-white bg-blue-600 rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500"
          >
            Sign In
          </button>
        </form>
      </div>
    </div>
  );
};

Example 2: Generate Multiple Components

示例2:生成多个组件

bash
undefined
bash
undefined

Create a components directory structure

创建组件目录结构

mkdir -p src/components/hero mkdir -p public/hero-assets
mkdir -p src/components/hero mkdir -p public/hero-assets

Convert hero section

转换Hero区块

npx vibefigma
"https://www.figma.com/design/YOUR_FILE_ID?node-id=HERO_NODE_ID"
--component ./src/components/hero/Hero.tsx
--assets ./public/hero-assets
--optimize
undefined
npx vibefigma
"https://www.figma.com/design/YOUR_FILE_ID?node-id=HERO_NODE_ID"
--component ./src/components/hero/Hero.tsx
--assets ./public/hero-assets
--optimize
undefined

Example 3: Without Tailwind (Regular CSS)

示例3:不使用Tailwind(常规CSS)

bash
npx vibefigma \
  "https://www.figma.com/design/YOUR_FILE_ID?node-id=NODE_ID" \
  --no-tailwind \
  --component ./src/components/CustomCard.tsx
This generates a component with inline styles or CSS modules instead of Tailwind classes.
bash
npx vibefigma \
  "https://www.figma.com/design/YOUR_FILE_ID?node-id=NODE_ID" \
  --no-tailwind \
  --component ./src/components/CustomCard.tsx
此命令会生成使用内联样式或CSS模块替代Tailwind类的组件。

API Server Usage

API服务器使用方法

VibeFigma includes a REST API for programmatic conversions.
VibeFigma包含一个REST API,用于程序化转换。

Starting the Server

启动服务器

bash
undefined
bash
undefined

Install dependencies

安装依赖

bun install
bun install

Development mode

开发模式

bun run dev
bun run dev

Production mode

生产模式

bun run start
undefined
bun run start
undefined

Configuration

配置

Create
.env
file:
env
GOOGLE_GENERATIVE_AI_API_KEY=your_google_ai_key_here
PORT=3000
HOST=0.0.0.0
CORS_ORIGIN=*
FIGMA_TOKEN=your_figma_token_here
创建
.env
文件:
env
GOOGLE_GENERATIVE_AI_API_KEY=your_google_ai_key_here
PORT=3000
HOST=0.0.0.0
CORS_ORIGIN=*
FIGMA_TOKEN=your_figma_token_here

API Endpoint

API端点

typescript
// POST /v1/api/vibe-figma
interface ConversionRequest {
  figmaUrl: string;
  token?: string; // Optional if FIGMA_TOKEN env var is set
  options?: {
    useTailwind?: boolean;
    optimize?: boolean;
    clean?: boolean;
    responsive?: boolean;
    includeFonts?: boolean;
  };
}

interface ConversionResponse {
  component: string; // Generated React component code
  assets: Array<{
    name: string;
    url: string;
    data?: string; // Base64 for embedded assets
  }>;
}
typescript
// POST /v1/api/vibe-figma
interface ConversionRequest {
  figmaUrl: string;
  token?: string; // 如果已设置FIGMA_TOKEN环境变量则可选
  options?: {
    useTailwind?: boolean;
    optimize?: boolean;
    clean?: boolean;
    responsive?: boolean;
    includeFonts?: boolean;
  };
}

interface ConversionResponse {
  component: string; // 生成的React组件代码
  assets: Array<{
    name: string;
    url: string;
    data?: string; // 嵌入资源的Base64编码
  }>;
}

Example API Call

API调用示例

typescript
const response = await fetch('http://localhost:3000/v1/api/vibe-figma', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    figmaUrl: 'https://www.figma.com/design/FILE_ID?node-id=NODE_ID',
    token: process.env.FIGMA_TOKEN,
    options: {
      useTailwind: true,
      optimize: true,
      responsive: true,
    },
  }),
});

const { component, assets } = await response.json();

// Write component to file
await fs.writeFile('./src/components/Generated.tsx', component);

// Download assets
for (const asset of assets) {
  const assetData = await fetch(asset.url);
  await fs.writeFile(`./public/${asset.name}`, await assetData.arrayBuffer());
}
typescript
const response = await fetch('http://localhost:3000/v1/api/vibe-figma', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    figmaUrl: 'https://www.figma.com/design/FILE_ID?node-id=NODE_ID',
    token: process.env.FIGMA_TOKEN,
    options: {
      useTailwind: true,
      optimize: true,
      responsive: true,
    },
  }),
});

const { component, assets } = await response.json();

// 将组件写入文件
await fs.writeFile('./src/components/Generated.tsx', component);

// 下载资源
for (const asset of assets) {
  const assetData = await fetch(asset.url);
  await fs.writeFile(`./public/${asset.name}`, await assetData.arrayBuffer());
}

Common Patterns

常见使用模式

Pattern 1: Batch Conversion Script

模式1:批量转换脚本

typescript
import { execSync } from 'child_process';
import path from 'path';

interface FigmaComponent {
  name: string;
  url: string;
  outputPath: string;
}

const components: FigmaComponent[] = [
  {
    name: 'Header',
    url: 'https://www.figma.com/design/FILE_ID?node-id=HEADER_NODE',
    outputPath: './src/components/Header.tsx',
  },
  {
    name: 'Footer',
    url: 'https://www.figma.com/design/FILE_ID?node-id=FOOTER_NODE',
    outputPath: './src/components/Footer.tsx',
  },
];

for (const comp of components) {
  console.log(`Converting ${comp.name}...`);
  execSync(
    `npx vibefigma "${comp.url}" --component ${comp.outputPath} --force`,
    { stdio: 'inherit' }
  );
}
typescript
import { execSync } from 'child_process';
import path from 'path';

interface FigmaComponent {
  name: string;
  url: string;
  outputPath: string;
}

const components: FigmaComponent[] = [
  {
    name: 'Header',
    url: 'https://www.figma.com/design/FILE_ID?node-id=HEADER_NODE',
    outputPath: './src/components/Header.tsx',
  },
  {
    name: 'Footer',
    url: 'https://www.figma.com/design/FILE_ID?node-id=FOOTER_NODE',
    outputPath: './src/components/Footer.tsx',
  },
];

for (const comp of components) {
  console.log(`正在转换${comp.name}...`);
  execSync(
    `npx vibefigma "${comp.url}" --component ${comp.outputPath} --force`,
    { stdio: 'inherit' }
  );
}

Pattern 2: CI/CD Integration

模式2:CI/CD集成

yaml
undefined
yaml
undefined

.github/workflows/figma-sync.yml

.github/workflows/figma-sync.yml

name: Sync Figma Designs
on: workflow_dispatch: schedule: - cron: '0 0 * * 1' # Weekly on Mondays
jobs: sync: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3
  - name: Setup Node.js
    uses: actions/setup-node@v3
    with:
      node-version: '18'
  
  - name: Convert Figma to React
    env:
      FIGMA_TOKEN: ${{ secrets.FIGMA_TOKEN }}
    run: |
      npx vibefigma "${{ vars.FIGMA_URL }}" \
        --component ./src/components/DesignSystem.tsx \
        --force
  
  - name: Create Pull Request
    uses: peter-evans/create-pull-request@v5
    with:
      title: 'chore: sync Figma designs'
      branch: figma-sync
undefined
name: Sync Figma Designs
on: workflow_dispatch: schedule: - cron: '0 0 * * 1' # 每周一执行
jobs: sync: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3
  - name: Setup Node.js
    uses: actions/setup-node@v3
    with:
      node-version: '18'
  
  - name: 转换Figma为React组件
    env:
      FIGMA_TOKEN: ${{ secrets.FIGMA_TOKEN }}
    run: |
      npx vibefigma "${{ vars.FIGMA_URL }}" \
        --component ./src/components/DesignSystem.tsx \
        --force
  
  - name: 创建Pull Request
    uses: peter-evans/create-pull-request@v5
    with:
      title: 'chore: sync Figma designs'
      branch: figma-sync
undefined

Pattern 3: Custom Post-Processing

模式3:自定义后处理

typescript
import { execSync } from 'child_process';
import fs from 'fs/promises';

async function convertAndCustomize(figmaUrl: string, outputPath: string) {
  // Generate component
  execSync(
    `npx vibefigma "${figmaUrl}" --component ${outputPath} --force`,
    { stdio: 'inherit' }
  );

  // Read generated file
  let content = await fs.readFile(outputPath, 'utf-8');

  // Add custom imports
  content = `import { motion } from 'framer-motion';\n${content}`;

  // Replace div with motion.div for animations
  content = content.replace(
    /<div className="/g,
    '<motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} className="'
  );
  content = content.replace(/<\/div>/g, '</motion.div>');

  // Write back
  await fs.writeFile(outputPath, content);
  
  console.log(`✅ Generated and customized: ${outputPath}`);
}

// Usage
await convertAndCustomize(
  'https://www.figma.com/design/FILE_ID?node-id=NODE_ID',
  './src/components/AnimatedHero.tsx'
);
typescript
import { execSync } from 'child_process';
import fs from 'fs/promises';

async function convertAndCustomize(figmaUrl: string, outputPath: string) {
  // 生成组件
  execSync(
    `npx vibefigma "${figmaUrl}" --component ${outputPath} --force`,
    { stdio: 'inherit' }
  );

  // 读取生成的文件
  let content = await fs.readFile(outputPath, 'utf-8');

  // 添加自定义导入
  content = `import { motion } from 'framer-motion';\n${content}`;

  // 将div替换为motion.div以实现动画
  content = content.replace(
    /<div className="/g,
    '<motion.div initial={{ opacity: 0 }} animate={{ opacity: 1 }} className="'
  );
  content = content.replace(/<\/div>/g, '</motion.div>');

  // 写回文件
  await fs.writeFile(outputPath, content);
  
  console.log(`✅ 已生成并自定义:${outputPath}`);
}

// 使用示例
await convertAndCustomize(
  'https://www.figma.com/design/FILE_ID?node-id=NODE_ID',
  './src/components/AnimatedHero.tsx'
);

Troubleshooting

问题排查

Issue: "Invalid Figma token"

问题:"Invalid Figma token"(无效的Figma令牌)

Solution: Verify your token is correct and not expired:
bash
undefined
解决方案:验证你的令牌是否正确且未过期:
bash
undefined

Test token manually

手动测试令牌

curl -H "X-Figma-Token: YOUR_TOKEN"
https://api.figma.com/v1/me
undefined
curl -H "X-Figma-Token: YOUR_TOKEN"
https://api.figma.com/v1/me
undefined

Issue: "Node not found"

问题:"Node not found"(节点未找到)

Solution: Ensure your Figma URL includes the correct
node-id
parameter:
bash
undefined
解决方案:确保你的Figma链接包含正确的
node-id
参数:
bash
undefined

Correct format

正确格式

You can copy this from Figma:

你可以从Figma复制:

Right-click frame → Copy/Paste → Copy link

右键点击框架 → 复制/粘贴 → 复制链接

undefined
undefined

Issue: Generated code has inline styles instead of Tailwind

问题:生成的代码使用内联样式而非Tailwind

Solution: Ensure Tailwind is not disabled:
bash
undefined
解决方案:确保未禁用Tailwind:
bash
undefined

Remove --no-tailwind flag

移除--no-tailwind参数

npx vibefigma [url] --component ./output.tsx
npx vibefigma [url] --component ./output.tsx

Explicitly enable optimization

显式开启优化

npx vibefigma [url] --component ./output.tsx --optimize
undefined
npx vibefigma [url] --component ./output.tsx --optimize
undefined

Issue: Assets not downloading

问题:资源未下载

Solution: Check asset directory permissions and path:
bash
undefined
解决方案:检查资源目录的权限和路径:
bash
undefined

Create directory first

先创建目录

mkdir -p ./public/assets
mkdir -p ./public/assets

Specify absolute path

指定绝对路径

npx vibefigma [url] --assets $(pwd)/public/assets
undefined
npx vibefigma [url] --assets $(pwd)/public/assets
undefined

Issue: Component has positioning issues

问题:组件定位有问题

Solution: Try disabling absolute positioning:
bash
npx vibefigma [url] --no-absolute --responsive
解决方案:尝试禁用绝对定位:
bash
npx vibefigma [url] --no-absolute --responsive

Issue: Fonts not loading

问题:字体未加载

Solution: Ensure font imports are enabled and Tailwind config includes fonts:
typescript
// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      fontFamily: {
        sans: ['Inter', 'system-ui', 'sans-serif'],
      },
    },
  },
};
解决方案:确保已启用字体导入,且Tailwind配置中包含字体:
typescript
// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      fontFamily: {
        sans: ['Inter', 'system-ui', 'sans-serif'],
      },
    },
  },
};

Integration with Development Workflow

与开发工作流集成

Next.js Integration

Next.js集成

bash
undefined
bash
undefined

Generate component in Next.js app directory

在Next.js应用目录中生成组件

npx vibefigma [url]
--component ./app/components/FigmaComponent.tsx
--assets ./public/figma-assets
undefined
npx vibefigma [url]
--component ./app/components/FigmaComponent.tsx
--assets ./public/figma-assets
undefined

Vite/React Integration

Vite/React集成

bash
undefined
bash
undefined

Generate for Vite project

为Vite项目生成组件

npx vibefigma [url]
--component ./src/components/FigmaComponent.tsx
--assets ./public/assets
undefined
npx vibefigma [url]
--component ./src/components/FigmaComponent.tsx
--assets ./public/assets
undefined

Storybook Integration

Storybook集成

typescript
// Generate component
// Then create story file

import type { Meta, StoryObj } from '@storybook/react';
import { FigmaComponent } from './FigmaComponent';

const meta: Meta<typeof FigmaComponent> = {
  title: 'Design System/FigmaComponent',
  component: FigmaComponent,
};

export default meta;
type Story = StoryObj<typeof FigmaComponent>;

export const Default: Story = {};
typescript
// 生成组件
// 然后创建故事文件

import type { Meta, StoryObj } from '@storybook/react';
import { FigmaComponent } from './FigmaComponent';

const meta: Meta<typeof FigmaComponent> = {
  title: 'Design System/FigmaComponent',
  component: FigmaComponent,
};

export default meta;
type Story = StoryObj<typeof FigmaComponent>;

export const Default: Story = {};

Best Practices

最佳实践

  1. Version Control: Always commit generated components to track design changes over time
  2. Naming Conventions: Use descriptive component names that match Figma frame names
  3. Asset Management: Organize assets in subdirectories per component
  4. Review Generated Code: Always review and test generated components before production use
  5. Incremental Updates: Use
    --force
    flag carefully; review diffs when regenerating existing components
  6. Environment Variables: Never commit tokens; always use environment variables
  7. AI Optimization: Use
    --clean
    flag only when GOOGLE_GENERATIVE_AI_API_KEY is available for better code quality
  1. 版本控制:始终提交生成的组件,以跟踪设计随时间的变化
  2. 命名规范:使用与Figma框架名称匹配的描述性组件名称
  3. 资源管理:按组件将资源组织到子目录中
  4. 代码审查:在投入生产使用前,务必审查并测试生成的组件
  5. 增量更新:谨慎使用
    --force
    参数;重新生成现有组件时需审查差异
  6. 环境变量:切勿提交令牌;始终使用环境变量存储
  7. AI优化:仅当GOOGLE_GENERATIVE_AI_API_KEY可用时才使用
    --clean
    参数,以获得更高的代码质量

Resources

相关资源