--- description: Intelligently clean up temporary artifacts and development files from the project allowed-tools: Task, TodoWrite, Read, Write, Edit, Glob, Bash, AskUserQuestion, mcp__figma__get_design_context --- # Import Figma Make Component Automates importing UI components from **Figma Make** projects into your React project with validation and iterative fixing. **Important:** This command works with **Figma Make** projects (URLs with `/make/` path), not regular Figma design files. Make projects contain actual working React/TypeScript code that can be imported directly. ## Prerequisites - **Figma Make project URL** must be in CLAUDE.md under "Design Resources" - Component must exist in your Make project - Development server should be running: `pnpm dev` - Figma MCP server must be authenticated (run `/configure-mcp` if needed) - **MCP Resources support** must be available (required for fetching Make files) ## Getting the Figma Make URL **Need help getting Figma Make URLs?** See the complete guide: [docs/figma-integration-guide.md](../../../docs/figma-integration-guide.md) ### Quick Instructions 1. **Create or open a Make project** in Figma (figma.com/make) 2. **Select the component** you want to export in your Make project 3. **Copy the URL** from the browser address bar 4. **Ensure the URL includes `/make/` in the path** Expected URL format: ``` https://www.figma.com/make/{projectId}/{projectName}?node-id={nodeId} ``` **Real Example:** ``` https://www.figma.com/make/DfMjRj4FzWcDHHIGRsypcM/Implement-Screen-in-Shadcn?node-id=0-1&t=GZmiQgdDkZ6PjFRG-1 ``` Add this URL to your `CLAUDE.md` under the "Design Resources" section: ```markdown ## Design Resources **Figma Make Project**: https://www.figma.com/make/DfMjRj4FzWcDHHIGRsypcM/Implement-Screen-in-Shadcn?node-id=0-1&t=GZmiQgdDkZ6PjFRG-1 ``` **Important:** The URL must contain `/make/` not `/file/` or `/design/` - only Make projects have importable code. ## Workflow Overview This command will: 1. Read CLAUDE.md and extract Figma Make project URL 2. Fetch component files from Make using **MCP Resources** 3. List available files from Make project 4. Select component code to import 5. Analyze and adapt component code for your project structure 6. Check for name collisions and prompt user if needed 7. Install any missing dependencies via pnpm 8. Create component file in appropriate location 9. Create test route at /playground/{component-name} 10. Invoke tester agent for validation 11. Apply fixes if validation fails (up to 5 iterations) 12. Update CLAUDE.md with component mapping 13. Present comprehensive summary **What makes this different:** Unlike traditional Figma design imports, Make projects contain real working code. The MCP Resources integration fetches actual React/TypeScript implementations with styles, interactions, and behaviors already defined. ## Implementation Instructions ### STEP 0: Discover Project Structure Before doing anything else, discover the project structure dynamically: 1. **Get current working directory** using Bash `pwd` command 2. **Find components directory** using Glob pattern `**/components/**/*.tsx` (exclude node_modules) 3. **Find routes directory** using Glob pattern `**/routes/**/*.tsx` (exclude node_modules) 4. **Analyze discovered paths** to determine: - Where components are stored (e.g., `src/components/`) - Where UI components are stored (e.g., `src/components/ui/`) - Where routes are stored (e.g., `src/routes/`) - Whether a playground directory exists in routes Example discovery logic: ```typescript // Get project root const projectRoot = await Bash({ command: 'pwd' }) // Find existing components const componentFiles = await Glob({ pattern: 'src/components/**/*.tsx' }) const uiComponentFiles = await Glob({ pattern: 'src/components/ui/**/*.tsx' }) const routeFiles = await Glob({ pattern: 'src/routes/**/*.tsx' }) // Determine paths based on discoveries const hasComponentsDir = componentFiles.length > 0 const hasUiDir = uiComponentFiles.length > 0 const hasRoutesDir = routeFiles.length > 0 // Set paths based on what exists const componentsBasePath = hasComponentsDir ? 'src/components' : 'components' const uiComponentsPath = hasUiDir ? 'src/components/ui' : 'src/components' const routesBasePath = hasRoutesDir ? 'src/routes' : 'routes' const playgroundPath = `${routesBasePath}/playground` ``` 5. **Store discovered paths** in variables for use throughout the command 6. **Detect package manager**: - Check for `pnpm-lock.yaml` → use pnpm - Check for `package-lock.json` → use npm - Check for `yarn.lock` → use yarn - Default to pnpm if none found 7. **Check for path aliases**: - Read tsconfig.json to check for `paths` configuration - Look for `@/*` or `~/*` aliases - Store whether aliases exist and what prefix to use ### Constants and Setup ```typescript const MAX_ITERATIONS = 5 // All paths will be determined dynamically in STEP 0: // - projectRoot // - componentsBasePath // - uiComponentsPath // - routesBasePath // - playgroundPath // - claudeMdPath // - packageManager ('pnpm' | 'npm' | 'yarn') // - pathAlias ({ exists: boolean, prefix: string }) ``` ### STEP 1: Initialize Todo Tracking Use TodoWrite to create a comprehensive task list for tracking progress: ```typescript TodoWrite({ todos: [ { content: 'Discover project structure', status: 'completed', activeForm: 'Discovering project structure' }, { content: 'Read CLAUDE.md and extract Figma URL', status: 'in_progress', activeForm: 'Reading CLAUDE.md and extracting Figma URL' }, { content: 'Fetch component from Figma', status: 'pending', activeForm: 'Fetching component from Figma' }, { content: 'Analyze and adapt component code', status: 'pending', activeForm: 'Analyzing and adapting component code' }, { content: 'Check for name collisions', status: 'pending', activeForm: 'Checking for name collisions' }, { content: 'Install required dependencies', status: 'pending', activeForm: 'Installing required dependencies' }, { content: 'Create component file', status: 'pending', activeForm: 'Creating component file' }, { content: 'Create test route', status: 'pending', activeForm: 'Creating test route' }, { content: 'Run validation tests', status: 'pending', activeForm: 'Running validation tests' }, { content: 'Update CLAUDE.md with mapping', status: 'pending', activeForm: 'Updating CLAUDE.md with mapping' }, { content: 'Present summary to user', status: 'pending', activeForm: 'Presenting summary to user' } ] }) ``` ### STEP 2: Read and Parse CLAUDE.md 1. **Locate CLAUDE.md** using Glob pattern: `**/CLAUDE.md` (search from project root) - If not found, check common locations: `./CLAUDE.md`, `./docs/CLAUDE.md`, `./.claude/CLAUDE.md` - If still not found, create it in project root with template structure 2. **Read CLAUDE.md file** 3. **Extract Figma URL** from "Design Resources" section 4. **Parse file key and node ID** from URL 5. **Handle errors** if URL is missing or malformed Expected Figma URL format: ``` **Figma Make URL**: https://www.figma.com/make/{fileKey}/{fileName}?node-id={nodeId} ``` Error handling: - If Figma URL not found, instruct user to add it to CLAUDE.md with format example - If URL format invalid, provide correct format and ask user to fix it Once successfully parsed: - Extract `fileKey` from URL - Extract `nodeId` and convert format from `123-456` to `123:456` - Update todo: mark "Read CLAUDE.md" as completed, mark "Fetch component" as in_progress ### STEP 3: Fetch Component from Figma Use the Figma MCP tool to fetch component design context: ```typescript mcp__figma__get_design_context({ fileKey: fileKey, nodeId: nodeId, clientFrameworks: 'react', clientLanguages: 'typescript' }) ``` Extract the `code` field from the response, which contains the component implementation. Error handling: - If component not found: Verify URL, node ID, and access permissions - If unauthorized: Check Figma authentication status - If API error: Display error message and suggest retrying Once component code is fetched successfully: - Store the code in a variable for adaptation - Update todo: mark "Fetch component" as completed, mark "Analyze and adapt" as in_progress ### STEP 4: Analyze and Adapt Component Code #### 4.1 Extract Component Name Parse the component code to find the exported component name using regex: ```regex /export\s+(?:function|const)\s+([A-Z][a-zA-Z0-9]*)/ ``` If component name cannot be extracted, throw error explaining that the component must have a PascalCase exported name. #### 4.2 Adapt Imports Apply these import transformations to adapt Figma code to our project structure: 1. **Utils import**: `from "./utils"` → `from "@/lib/utils"` 2. **Component imports**: `from "./button"` → `from "@/components/ui/button"` 3. **React namespace imports**: Add `type` keyword: `import type * as React from "react"` #### 4.3 Ensure cn() Import If the component uses the `cn()` utility function but doesn't import it: - Find the React import line - Insert `import { cn } from "@/lib/utils"` right after the React import #### 4.4 Determine Component Location Use this logic to determine where to save the component (using discovered paths from STEP 0): ```typescript const usesRadixUI = code includes "@radix-ui" const uiPrimitives = ['Button', 'Input', 'Card', 'Badge', 'Avatar', 'Alert', 'Checkbox', 'Select', 'Dialog', 'Dropdown', 'Menu', 'Popover', 'Tooltip', 'Toast', 'Tabs', 'Table', 'Form', 'Label', 'Switch', 'Slider', 'Progress'] const isPrimitive = componentName matches any uiPrimitives if (usesRadixUI || isPrimitive) { // UI primitive component → use discovered uiComponentsPath const kebabName = toKebabCase(componentName) componentPath = `${projectRoot}/${uiComponentsPath}/${kebabName}.tsx` } else { // Feature component → use discovered componentsBasePath componentPath = `${projectRoot}/${componentsBasePath}/${componentName}.tsx` } ``` Convert PascalCase to kebab-case: `UserCard` → `user-card` **Important**: Use the paths discovered in STEP 0, don't hardcode `src/components/` Once adaptation is complete: - Update todo: mark "Analyze and adapt" as completed, mark "Check for name collisions" as in_progress ### STEP 5: Check for Name Collisions #### 5.1 Check if Component Exists Use Glob to check if a file already exists at the determined component path. #### 5.2 If Collision Found, Ask User Use AskUserQuestion to prompt the user: ```typescript AskUserQuestion({ questions: [{ question: `A component named "${componentName}" already exists at ${componentPath}. What would you like to do?`, header: "Name Collision", multiSelect: false, options: [ { label: "Overwrite existing", description: "Replace the existing component with the new one from Figma" }, { label: "Create versioned copy", description: `Save as ${componentName}V2.tsx (or next available version)` }, { label: "Cancel import", description: "Abort the import process without making changes" } ] }] }) ``` #### 5.3 Handle User Decision - **Cancel import**: Throw error to stop execution - **Overwrite existing**: Continue with same componentPath (file will be replaced) - **Create versioned copy**: - Find next available version number (V2, V3, ..., up to V99) - Update componentPath to versioned name - Update component name in the code to match versioned name Once collision is resolved: - Update todo: mark "Check for name collisions" as completed, mark "Install required dependencies" as in_progress ### STEP 6: Install Required Dependencies #### 6.1 Extract Required Packages Parse all import statements from the adapted code: ```regex /^import\s+.*$/gm ``` For each import line, extract the module name from `from "..."` Filter to only external packages (exclude): - Imports starting with `@/` (our project) - Imports starting with `.` (relative imports) - `react` and `react-dom` (always installed) Common packages that might be needed: - `@radix-ui/*` - `class-variance-authority` - `lucide-react` - `cmdk` - `embla-carousel-react` - `recharts` #### 6.2 Check What's Already Installed Read package.json and check both `dependencies` and `devDependencies` sections. Filter the required packages list to only those not already installed. #### 6.3 Install Missing Dependencies If there are packages to install: ```bash cd {projectRoot} && {packageManager} add {package1} {package2} ... ``` Use the detected package manager from STEP 0 (pnpm/npm/yarn). Use Bash tool with timeout of 60000ms (1 minute). Error handling: - If installation fails, provide clear error message with manual installation command - Suggest user runs `pnpm add {packages}` manually and then re-runs /import-figma Once dependencies are installed (or confirmed already installed): - Update todo: mark "Install required dependencies" as completed, mark "Create component file" as in_progress ### STEP 7: Create Component File #### 7.1 Write Component File Use Write tool to create the component file with the adapted code at the determined componentPath. #### 7.2 Apply Code Formatting Check which formatter is configured: - Look for `biome.json` → use Biome - Look for `.eslintrc*` → use ESLint - Look for `.prettierrc*` → use Prettier Run the appropriate formatter: ```bash # If Biome exists: cd {projectRoot} && {packageManager} run lint:fix {componentPath} # If ESLint exists: cd {projectRoot} && {packageManager} run lint {componentPath} --fix # If Prettier exists: cd {projectRoot} && {packageManager} run format {componentPath} ``` If formatting fails, log warning but continue (non-critical). Once component file is created: - Update todo: mark "Create component file" as completed, mark "Create test route" as in_progress ### STEP 8: Create Test Route #### 8.1 Determine Test Route Path Use the discovered routes path from STEP 0: ```typescript const kebabName = toKebabCase(componentName) // UserCard -> user-card // Check if playground directory exists const playgroundExists = await Glob({ pattern: `${playgroundPath}/**` }) // Create playground directory if it doesn't exist if (playgroundExists.length === 0) { await Bash({ command: `mkdir -p ${projectRoot}/${playgroundPath}` }) } const testRoutePath = `${projectRoot}/${playgroundPath}/${kebabName}.tsx` ``` **Important**: Use the `playgroundPath` discovered in STEP 0, don't hardcode `src/routes/playground/` #### 8.2 Analyze Component Props Check if component has props by looking for interface/type definitions: ```regex /(?:interface|type)\s+\w+Props\s*=?\s*{([^}]+)}/ ``` #### 8.3 Generate Test Route Content Create a test route that: - Imports the component correctly (use discovered paths, not hardcoded @/ aliases) - Uses TanStack Router's `createFileRoute` - Renders the component in an isolated playground environment - Includes heading, description, and test sections - Uses dummy data if component has props (add TODO comment for user to customize) **Determine import path dynamically**: ```typescript // Calculate relative import path from test route to component // Example: if component is in src/components/ui/button.tsx // and test route is in src/routes/playground/button.tsx // then import path is "../../components/ui/button" const importPath = calculateRelativePath(testRoutePath, componentPath) // OR use project's alias if it exists (@/ or ~/) const hasPathAlias = await checkForPathAlias() // Check tsconfig.json or vite.config const importStatement = hasPathAlias ? `import { ${componentName} } from "@/${componentsBasePath}/${componentName}"` : `import { ${componentName} } from "${importPath}"` ``` Template structure (with dynamic import): ```typescript import { createFileRoute } from "@tanstack/react-router" ${importStatement} export const Route = createFileRoute("/playground/${kebabName}")({ component: PlaygroundComponent, }) function PlaygroundComponent() { // Sample data if component has props return (
Testing playground for ${componentName} imported from Figma