Initial commit
This commit is contained in:
832
commands/import-figma.md
Normal file
832
commands/import-figma.md
Normal file
@@ -0,0 +1,832 @@
|
||||
---
|
||||
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 (
|
||||
<div className="min-h-screen bg-background p-8">
|
||||
<div className="mx-auto max-w-4xl space-y-8">
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold mb-2">${componentName} Playground</h1>
|
||||
<p className="text-muted-foreground">Testing playground for ${componentName} imported from Figma</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-6">
|
||||
<section className="space-y-4">
|
||||
<h2 className="text-xl font-semibold">Default Variant</h2>
|
||||
<div className="p-6 border rounded-lg bg-card">
|
||||
<${componentName} />
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
**Important**: Don't hardcode `@/components/` - use the discovered path or calculate relative import
|
||||
|
||||
#### 8.4 Write and Format Test Route
|
||||
|
||||
- Use Write tool to create the test route file
|
||||
- Run Biome formatting on the test route file
|
||||
|
||||
Once test route is created:
|
||||
- Update todo: mark "Create test route" as completed, mark "Run validation tests" as in_progress
|
||||
|
||||
### STEP 9: Run Validation Tests
|
||||
|
||||
This is a critical step that uses an iterative validation loop with the tester agent.
|
||||
|
||||
#### 9.1 Initialize Loop Variables
|
||||
|
||||
```typescript
|
||||
iteration = 0
|
||||
testPassed = false
|
||||
testResult = ''
|
||||
```
|
||||
|
||||
#### 9.2 Validation Loop (Max 5 Iterations)
|
||||
|
||||
While `iteration < MAX_ITERATIONS` and `!testPassed`:
|
||||
|
||||
**A. Invoke tester Agent**
|
||||
|
||||
Use Task tool to invoke the tester agent with comprehensive testing instructions:
|
||||
|
||||
```typescript
|
||||
Task({
|
||||
subagent_type: 'frontend:tester',
|
||||
description: `Test ${componentName} component`,
|
||||
prompt: `Test the ${componentName} component at /playground/${kebabName}
|
||||
|
||||
## Component Details
|
||||
- **Name**: ${componentName}
|
||||
- **Location**: ${componentPath.replace(projectRoot + '/', '')}
|
||||
- **Test Route**: /playground/${kebabName}
|
||||
- **Test URL**: http://localhost:5173/playground/${kebabName}
|
||||
|
||||
Note: Use relative paths in the test instructions, not absolute paths
|
||||
|
||||
## Test Scenarios
|
||||
|
||||
1. **Navigation Test**
|
||||
- Navigate to http://localhost:5173/playground/${kebabName}
|
||||
- Verify page loads without errors
|
||||
|
||||
2. **Console Check**
|
||||
- Open browser DevTools console
|
||||
- Verify no errors or warnings
|
||||
- Check for missing imports or type errors
|
||||
|
||||
3. **Visual Rendering**
|
||||
- Verify component renders correctly
|
||||
- Check spacing, colors, typography
|
||||
- Ensure no layout issues
|
||||
|
||||
4. **Interaction Testing** (if applicable)
|
||||
- Test any buttons, inputs, or interactive elements
|
||||
- Verify event handlers work correctly
|
||||
|
||||
5. **Responsive Testing**
|
||||
- Test at mobile (375px), tablet (768px), desktop (1440px)
|
||||
- Verify layout adapts correctly
|
||||
|
||||
## Pass Criteria
|
||||
|
||||
- ✓ No console errors
|
||||
- ✓ Component renders without crashes
|
||||
- ✓ Visual appearance is acceptable
|
||||
- ✓ All interactions work as expected
|
||||
|
||||
## Report Format
|
||||
|
||||
Please provide:
|
||||
1. **Overall Status**: PASS or FAIL
|
||||
2. **Errors Found**: List any console errors
|
||||
3. **Visual Issues**: Describe rendering problems (if any)
|
||||
4. **Recommendations**: Suggest fixes if issues found
|
||||
|
||||
This is iteration ${iteration + 1} of ${MAX_ITERATIONS}.`
|
||||
})
|
||||
```
|
||||
|
||||
**B. Parse Test Result**
|
||||
|
||||
Check if the test result contains "Overall Status" with "PASS" (case-insensitive).
|
||||
|
||||
If PASS:
|
||||
- Set `testPassed = true`
|
||||
- Break out of loop
|
||||
|
||||
If FAIL and not at max iterations yet:
|
||||
- Continue to fix strategy
|
||||
|
||||
**C. Apply Automated Fixes**
|
||||
|
||||
Identify common error patterns and attempt to fix them automatically:
|
||||
|
||||
**Fix Pattern 1: Missing Imports**
|
||||
|
||||
If error contains `"Cannot find module"` or `"Failed to resolve import"`:
|
||||
- Extract the missing module name
|
||||
- If it's a relative import (`./{name}`), convert to absolute: `@/components/ui/{name}`
|
||||
- Use Edit tool to replace the import path
|
||||
|
||||
**Fix Pattern 2: Missing cn Import**
|
||||
|
||||
If error contains `"cn is not defined"` or `"Cannot find name 'cn'"`:
|
||||
- Read the component file
|
||||
- Check if cn is already imported
|
||||
- If not, add `import { cn } from "@/lib/utils"` after React import
|
||||
- Use Write tool to update file
|
||||
|
||||
**Fix Pattern 3: Wrong Import Path**
|
||||
|
||||
If error suggests component not found:
|
||||
- Check if the imported component exists in a different location
|
||||
- Try alternative paths: `@/components/ui/{name}`, `@/components/{Name}`, etc.
|
||||
- Use Edit tool to fix the import
|
||||
|
||||
**Fix Pattern 4: Missing Dependency**
|
||||
|
||||
If error mentions a missing package:
|
||||
- Use pnpm to install the package
|
||||
- Rebuild if necessary
|
||||
|
||||
**Fix Pattern 5: Type Errors**
|
||||
|
||||
If error mentions missing properties or type mismatches:
|
||||
- Consider extending the component props interface
|
||||
- Add React.ComponentProps extension if needed
|
||||
|
||||
After applying fixes:
|
||||
- Reformat the file with Biome
|
||||
- Increment iteration counter
|
||||
- Loop back to invoke tester again
|
||||
|
||||
#### 9.3 Max Iterations Exceeded
|
||||
|
||||
If `iteration >= MAX_ITERATIONS` and `!testPassed`:
|
||||
|
||||
Use AskUserQuestion to prompt the user:
|
||||
|
||||
```typescript
|
||||
AskUserQuestion({
|
||||
questions: [{
|
||||
question: `The ${componentName} component still has validation issues after ${MAX_ITERATIONS} fix attempts. What would you like to do?`,
|
||||
header: "Validation Failed",
|
||||
multiSelect: false,
|
||||
options: [
|
||||
{ label: "Continue trying", description: "Attempt more fix iterations (may not resolve issues)" },
|
||||
{ label: "Keep as-is", description: "Save component despite issues for manual fixing later" },
|
||||
{ label: "Rollback changes", description: "Delete the imported component and test route" }
|
||||
]
|
||||
}]
|
||||
})
|
||||
```
|
||||
|
||||
Handle user decision:
|
||||
- **Continue trying**: Reset MAX_ITERATIONS and continue loop
|
||||
- **Keep as-is**: Break loop and continue to next step (component saved with issues)
|
||||
- **Rollback changes**: Delete component file and test route using Bash `rm` command, then throw error
|
||||
|
||||
Once validation is complete (either passed or user decided to keep/continue):
|
||||
- Update todo: mark "Run validation tests" as completed, mark "Update CLAUDE.md with mapping" as in_progress
|
||||
|
||||
### STEP 10: Update CLAUDE.md with Mapping
|
||||
|
||||
#### 10.1 Prepare Mapping Entry
|
||||
|
||||
```typescript
|
||||
const today = new Date().toISOString().split('T')[0] // YYYY-MM-DD format
|
||||
const status = testPassed ? '✓ Validated' : '⚠ Needs Review'
|
||||
```
|
||||
|
||||
#### 10.2 Check if Mappings Section Exists
|
||||
|
||||
Read CLAUDE.md and check if it contains "## Figma Component Mappings"
|
||||
|
||||
**If section doesn't exist:**
|
||||
|
||||
Add the complete section to the end of CLAUDE.md:
|
||||
|
||||
```markdown
|
||||
|
||||
## Figma Component Mappings
|
||||
|
||||
Imported components from Figma with their file locations and node IDs:
|
||||
|
||||
| Component Name | File Path | Figma Node ID | Import Date | Status |
|
||||
|----------------|-----------|---------------|-------------|--------|
|
||||
| {componentName} | {relativePath} | {nodeId} | {today} | {status} |
|
||||
|
||||
**Note**: This registry is automatically maintained by the `/import-figma` command.
|
||||
```
|
||||
|
||||
**If section exists:**
|
||||
|
||||
Find the table and append a new row:
|
||||
|
||||
```markdown
|
||||
| {componentName} | {relativePath} | {nodeId} | {today} | {status} |
|
||||
```
|
||||
|
||||
Use Edit tool to insert the new row.
|
||||
|
||||
Important: Use relative path (remove PROJECT_ROOT from path) for readability.
|
||||
|
||||
Once CLAUDE.md is updated:
|
||||
- Update todo: mark "Update CLAUDE.md with mapping" as completed, mark "Present summary to user" as in_progress
|
||||
|
||||
### STEP 11: Present Summary to User
|
||||
|
||||
Generate and present a comprehensive summary of the import operation.
|
||||
|
||||
#### Summary Structure:
|
||||
|
||||
```markdown
|
||||
# Figma Import Summary: {ComponentName}
|
||||
|
||||
## Status: {STATUS} {EMOJI}
|
||||
|
||||
### Component Details
|
||||
- **Name**: {componentName}
|
||||
- **Location**: {componentPath}
|
||||
- **Type**: {UI Component or Feature Component}
|
||||
- **Import Date**: {today}
|
||||
|
||||
### Test Route
|
||||
- **URL**: http://localhost:5173/playground/{kebab-name}
|
||||
- **File**: {testRoutePath}
|
||||
|
||||
### Dependencies
|
||||
{If packages installed}
|
||||
**Installed ({count} packages)**:
|
||||
- {package1}
|
||||
- {package2}
|
||||
...
|
||||
{Otherwise}
|
||||
No new dependencies required.
|
||||
|
||||
### Validation Results
|
||||
**Test Status**: {PASS ✓ or FAIL ✗}
|
||||
**Iterations**: {iteration} of {MAX_ITERATIONS}
|
||||
|
||||
{If passed}
|
||||
✓ All tests passed
|
||||
✓ No console errors
|
||||
✓ Component renders correctly
|
||||
|
||||
{If failed}
|
||||
⚠ Validation completed with issues
|
||||
|
||||
Please review the component at /playground/{kebab-name} and fix any remaining issues manually.
|
||||
|
||||
**Test Output**:
|
||||
{testResult}
|
||||
|
||||
### Next Steps
|
||||
{If passed}
|
||||
1. Visit /playground/{kebab-name} to view the component
|
||||
2. Review the component code at {componentPath}
|
||||
3. Integrate into your application as needed
|
||||
|
||||
{If failed}
|
||||
1. Visit /playground/{kebab-name} to review the component
|
||||
2. Check browser console for any errors
|
||||
3. Manually fix issues in {componentPath}
|
||||
4. Test thoroughly before production use
|
||||
|
||||
### Files Modified
|
||||
- Created: {componentPath}
|
||||
- Created: {testRoutePath}
|
||||
- Updated: CLAUDE.md (component mapping added)
|
||||
{If dependencies installed}
|
||||
- Updated: package.json (dependencies)
|
||||
- Updated: pnpm-lock.yaml (lockfile)
|
||||
```
|
||||
|
||||
#### Final Todo Update
|
||||
|
||||
Mark "Present summary to user" as completed.
|
||||
|
||||
All 10 steps should now be marked as completed in the todo list.
|
||||
|
||||
---
|
||||
|
||||
## Error Handling Reference
|
||||
|
||||
Throughout execution, handle these common errors gracefully:
|
||||
|
||||
1. **CLAUDE.md not found**: Provide instructions to create it with Figma URL
|
||||
2. **Figma URL missing**: Show exact format needed and where to add it
|
||||
3. **Invalid Figma URL**: Explain correct format with example
|
||||
4. **Figma API errors**: Check authentication, access, and retry
|
||||
5. **Component not found**: Verify node ID and file access
|
||||
6. **Name collision**: Always ask user (covered in Step 5)
|
||||
7. **Dependency installation failure**: Provide manual installation command
|
||||
8. **Write failures**: Check file permissions and paths
|
||||
9. **Validation failures**: Use iterative fixing (covered in Step 9)
|
||||
10. **Max iterations exceeded**: Always ask user (covered in Step 9)
|
||||
|
||||
## Helper Functions for Dynamic Path Resolution
|
||||
|
||||
### toKebabCase(str)
|
||||
Convert PascalCase to kebab-case:
|
||||
```typescript
|
||||
function toKebabCase(str: string): string {
|
||||
return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase()
|
||||
}
|
||||
// Example: UserCard → user-card
|
||||
```
|
||||
|
||||
### discoverProjectStructure()
|
||||
Returns object with all discovered paths:
|
||||
```typescript
|
||||
{
|
||||
projectRoot: '/absolute/path/to/project',
|
||||
componentsBasePath: 'src/components',
|
||||
uiComponentsPath: 'src/components/ui',
|
||||
routesBasePath: 'src/routes',
|
||||
playgroundPath: 'src/routes/playground',
|
||||
hasPathAlias: true, // @/ exists in tsconfig
|
||||
claudeMdPath: '/absolute/path/to/CLAUDE.md'
|
||||
}
|
||||
```
|
||||
|
||||
### calculateRelativePath(from, to)
|
||||
Calculate relative import path between two files:
|
||||
```typescript
|
||||
// from: /project/src/routes/playground/button.tsx
|
||||
// to: /project/src/components/ui/button.tsx
|
||||
// returns: ../../components/ui/button
|
||||
```
|
||||
|
||||
### checkForPathAlias()
|
||||
Check if project uses path alias (@/ or ~/) by reading tsconfig.json or vite.config:
|
||||
```typescript
|
||||
// Returns: { exists: true, prefix: '@/' } or { exists: false, prefix: null }
|
||||
```
|
||||
|
||||
## Important Notes
|
||||
|
||||
- **DO NOT hardcode any paths** - always use discovered paths from STEP 0
|
||||
- **All file paths must be absolute** when using tools (construct using projectRoot + relativePath)
|
||||
- **Use package manager from project** - detect pnpm/npm/yarn by checking lock files
|
||||
- Apply Biome formatting after all file creation/edits
|
||||
- Keep user informed via TodoWrite updates throughout
|
||||
- Use Task tool only for tester agent (no other agents)
|
||||
- Maximum 5 validation iterations before asking user
|
||||
- Always provide clear, actionable error messages
|
||||
- Preserve user control via AskUserQuestion for critical decisions
|
||||
- **Adapt to project conventions** - use existing import patterns, component structure, etc.
|
||||
|
||||
## Testing Checklist
|
||||
|
||||
Before marking complete, verify:
|
||||
- [ ] Component file created at correct location
|
||||
- [ ] Test route accessible at /playground/{name}
|
||||
- [ ] No console errors in browser
|
||||
- [ ] Component renders without crashing
|
||||
- [ ] CLAUDE.md updated with mapping entry
|
||||
- [ ] Summary presented to user
|
||||
- [ ] All todos marked as completed
|
||||
|
||||
---
|
||||
|
||||
**Command complete when all 10 steps are successfully executed and summary is presented to user.**
|
||||
Reference in New Issue
Block a user