{
  "openapi": "3.0.1",
  "info": {
    "title": "Figma to Next.js Code Generator",
    "description": "AI-powered Figma to Next.js code generator. Converts Figma designs to React components with Tailwind CSS. Auto-generates landing pages, dashboards, and complete websites. Claude AI included - no API key needed.",
    "version": "0.0",
    "x-build-id": "9DTs3LBbtheCAO6ci"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/enforceable_orbit~figma-actor/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-enforceable_orbit-figma-actor",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/acts/enforceable_orbit~figma-actor/runs": {
      "post": {
        "operationId": "runs-sync-enforceable_orbit-figma-actor",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor and returns information about the initiated run in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/runsResponseSchema"
                }
              }
            }
          }
        }
      }
    },
    "/acts/enforceable_orbit~figma-actor/run-sync": {
      "post": {
        "operationId": "run-sync-enforceable_orbit-figma-actor",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "inputSchema": {
        "type": "object",
        "required": [
          "figmaFileKey",
          "figmaAccessToken"
        ],
        "properties": {
          "figmaFileKey": {
            "title": "📁 Figma File Key",
            "type": "string",
            "description": "The file key from your Figma URL. <strong>Example:</strong> If your URL is <code>figma.com/file/<strong>abc123def456</strong>/My-Design</code>, the file key is <code>abc123def456</code><br><br><strong>Where to find it:</strong> Open your Figma file → Look at the browser URL → Copy the alphanumeric string after <code>/file/</code><br><br><strong>Try with example:</strong> Use <code>1156860863353724933</code> to test with our <a href='https://www.figma.com/community/file/1156860863353724933' target='_blank'>Whitepace SaaS Landing Page</a>"
          },
          "figmaAccessToken": {
            "title": "🔑 Figma Personal Access Token",
            "type": "string",
            "description": "Your Figma Personal Access Token for API access. Must start with <code>figd_</code><br><br><strong>How to get your token:</strong><br>1. Go to <a href='https://www.figma.com/settings' target='_blank'>Figma Settings → Account</a><br>2. Scroll to <strong>Personal Access Tokens</strong><br>3. Click <strong>Generate new token</strong><br>4. Give it a name (e.g., 'Code Generator')<br>5. Copy the token and paste it here<br><br><strong>⚠️ Note:</strong> Keep your token secure! It provides access to your Figma files."
          },
          "componentNaming": {
            "title": "🏷️ Component Naming Convention",
            "enum": [
              "PascalCase",
              "camelCase",
              "kebab-case"
            ],
            "type": "string",
            "description": "Choose how to name generated React components in your code.<br><br><strong>PascalCase</strong> (recommended) - Standard React convention: <code>MyComponent</code><br><strong>camelCase</strong> - Lowercase first letter: <code>myComponent</code><br><strong>kebab-case</strong> - Hyphenated lowercase: <code>my-component</code><br><br><strong>💡 Tip:</strong> Use PascalCase for React best practices.",
            "default": "PascalCase"
          },
          "includeTypeScript": {
            "title": "📘 Generate TypeScript",
            "type": "boolean",
            "description": "Enable this to generate TypeScript (<code>.tsx</code>) files with full type safety instead of JavaScript (<code>.jsx</code>).<br><br><strong>Why TypeScript?</strong><br>• Better IDE autocomplete and intellisense<br>• Catch errors before runtime<br>• Self-documenting code with type annotations<br>• Industry standard for modern React development<br><br><strong>✅ Recommended:</strong> Keep this enabled unless you specifically need JavaScript.",
            "default": true
          },
          "websiteMode": {
            "title": "🌐 Website Mode",
            "enum": [
              "landing-page",
              "multi-page"
            ],
            "type": "string",
            "description": "Choose the generation mode based on your Figma design structure.<br><br><strong>🎨 Landing Page Mode</strong> (Single responsive page)<br>• Automatically extracts sections from your frame<br>• Perfect for: Marketing pages, portfolios, product pages<br>• No frame names needed - just point to your Figma file!<br><br><strong>📄 Multi-Page Mode</strong> (Complete website)<br>• Creates separate pages with routing and navigation<br>• Perfect for: Full websites, SaaS apps, multi-page sites<br>• Requires: Exact frame names in <code>frameNames</code> field<br>• Optional: Prototype flows for navigation<br><br><strong>💡 Tip:</strong> Start with Landing Page mode if you're unsure - it's simpler!",
            "default": "landing-page"
          },
          "frameNames": {
            "title": "📄 Frame Names",
            "type": "array",
            "description": "<strong>⚠️ Required for Multi-Page mode</strong><br><br>Enter the <strong>exact names</strong> of Figma frames to convert into pages. Each frame becomes a separate page in your website.<br><br><strong>Important:</strong><br>• Names are <strong>case-sensitive</strong>: 'Home' ≠ 'home'<br>• Copy names directly from your Figma layers panel<br>• First frame (or 'Home') becomes the homepage (<code>/</code>)<br>• Other frames become routes like <code>/pricing</code>, <code>/about</code><br><br><strong>Example:</strong><br>• Frame 'Home' → <code>/</code> (homepage)<br>• Frame 'Pricing' → <code>/pricing</code><br>• Frame 'Contact' → <code>/contact</code><br><br><strong>💡 Tip:</strong> Check the <a href='#multi-page-mode-structure' target='_blank'>Multi-Page Structure Guide</a> in the README for proper Figma setup.",
            "items": {
              "type": "string"
            },
            "default": []
          },
          "usePrototypeNavigation": {
            "title": "🔗 Use Prototype Navigation",
            "type": "boolean",
            "description": "Generate navigation components based on your Figma prototype flows.<br><br><strong>When enabled:</strong><br>• Actor analyzes your Figma prototype interactions<br>• Creates navigation based on click actions between frames<br>• Generates proper Next.js <code>&lt;Link&gt;</code> components<br>• Results in more accurate navigation matching your design intent<br><br><strong>When disabled:</strong><br>• Navigation generated from frame order only<br>• All frames included in navigation<br>• May not match your intended user flow<br><br><strong>💡 How to set up prototype flows in Figma:</strong><br>1. Select a button/link in your Figma frame<br>2. Go to Prototype tab (right panel)<br>3. Add interaction: Click → Navigate to → [Target Frame]<br>4. Repeat for all navigation elements<br><br><strong>✅ Recommended:</strong> Keep enabled if you've set up prototype flows in Figma. See <a href='#multi-page-mode-prototype-navigation-requirements' target='_blank'>Prototype Navigation Guide</a>.",
            "default": true
          },
          "selectedPages": {
            "title": "⚙️ Pages to Convert",
            "type": "array",
            "description": "<strong>Optional:</strong> Filter which Figma <em>pages</em> to process (not to be confused with frames).<br><br>In Figma, pages are the tabs at the top (like 'Page 1', 'Page 2'). Leave empty to process all pages.<br><br><strong>Example use cases:</strong><br>• Your file has multiple pages for different projects<br>• You only want to convert designs from a specific page<br>• Testing with a subset of your design<br><br><strong>⚠️ Note:</strong> Page names are <strong>case-sensitive</strong>. Copy them exactly from Figma.<br><br><strong>💡 Tip:</strong> Most users should leave this empty to process all pages.",
            "items": {
              "type": "string"
            },
            "default": []
          },
          "sectionExtractionDepth": {
            "title": "🔍 Section Extraction Depth",
            "minimum": 1,
            "maximum": 10,
            "type": "integer",
            "description": "How many layers deep to traverse when extracting sections from frames (1-10).<br><br><strong>What this means:</strong><br>• Controls how deep the Actor looks for section elements<br>• <strong>1</strong> = Only direct children of frames (fastest, recommended)<br>• <strong>5</strong> = Default, handles most design structures<br>• <strong>10</strong> = Maximum depth for complex nested designs<br><br><strong>When to increase:</strong><br>• Your sections are nested inside multiple groups<br>• You're getting 'Too few sections' warnings<br>• Your Figma structure is legitimately complex<br><br><strong>⚠️ Trade-offs:</strong><br>• Higher values = More thorough but slower processing<br>• Higher values = May extract unwanted nested elements<br><br><strong>✅ Recommended:</strong> Keep default (5) unless you have specific nesting needs. See <a href='#-problem-too-few-sections-generated' target='_blank'>Troubleshooting Guide</a>.",
            "default": 5
          },
          "maxRequestsPerCrawl": {
            "title": "🚦 Max API Requests",
            "minimum": 10,
            "maximum": 1000,
            "type": "integer",
            "description": "Maximum number of Figma API requests to prevent excessive usage on very large files.<br><br><strong>What this controls:</strong><br>• Safety limit to prevent runaway API usage<br>• Typical files use 10-50 requests<br>• Large files (100+ frames) may need more<br><br><strong>When to increase:</strong><br>• You have a very large Figma file (> 50 frames)<br>• You're getting 'Max requests reached' errors<br>• You're processing multiple pages with many frames<br><br><strong>⚠️ Note:</strong> Each request costs a small amount. Higher limits = potentially higher costs for very large files.<br><br><strong>✅ Recommended:</strong> Keep default (100) for most projects. Only increase for enterprise-scale Figma files.",
            "default": 100
          },
          "enableVisualTesting": {
            "title": "🧪 Enable Visual Testing",
            "type": "boolean",
            "description": "<strong>EXPERIMENTAL - Phase 6</strong><br><br>Automatically test generated code against Figma designs using visual regression testing.<br><br><strong>What it does:</strong><br>• Launches generated Next.js code in headless browser<br>• Captures screenshots of each section<br>• Compares screenshots with Figma references using pixel-level comparison<br>• Attempts to fix sections that fail visual tests (iterative correction)<br>• Generates detailed HTML diff report<br><br><strong>⚠️ Important:</strong><br>• Adds 3-5 minutes to generation time<br>• Requires downloading Playwright browsers (~100MB first run)<br>• Uses additional compute resources<br>• May fail on complex layouts or animations<br><br><strong>Benefits:</strong><br>• Higher accuracy: Automatically catches visual discrepancies<br>• Quality assurance: Get reports showing exact differences<br>• Iterative fixes: AI re-generates failed sections with corrections<br><br><strong>💡 Recommended:</strong> Disable for testing. Enable for production-quality output when time allows.",
            "default": false
          },
          "visualTestingThreshold": {
            "title": "📊 Visual Difference Threshold (%)",
            "minimum": 0,
            "maximum": 100,
            "type": "integer",
            "description": "Maximum acceptable visual difference percentage (0-100) between Figma design and generated code.<br><br><strong>How it works:</strong><br>• After generating code, each section is compared pixel-by-pixel with Figma<br>• Difference is calculated as percentage of mismatched pixels<br>• Sections exceeding threshold are marked as failed<br>• Failed sections trigger automatic regeneration with corrections<br><br><strong>Threshold guidelines:</strong><br>• <strong>3%</strong> = Very strict (near-perfect match, may be too sensitive)<br>• <strong>5%</strong> = Recommended (catches significant differences, tolerates minor variations)<br>• <strong>10%</strong> = Moderate (allows more variation in fonts, spacing)<br>• <strong>15%+</strong> = Lenient (only catches major layout issues)<br><br><strong>What causes differences:</strong><br>• Font rendering variations (browser vs Figma)<br>• Anti-aliasing differences<br>• Spacing/padding minor deviations<br>• Color rounding (hex to RGB conversions)<br><br><strong>✅ Recommended:</strong> Start with 5% for balanced accuracy.",
            "default": 5
          },
          "enableIconVerification": {
            "title": "🎨 Enable Icon Verification",
            "type": "boolean",
            "description": "<strong>EXPERIMENTAL - Phase 6.5</strong><br><br>Visually verify that downloaded icons match their appearance in Figma designs.<br><br><strong>What it does:</strong><br>• Captures high-res screenshots of icons from Figma<br>• Compares screenshots with downloaded icon files<br>• Automatically retries failed icons with alternative formats/scales<br>• Tries: SVG 1x, SVG 2x, PNG 2x, PNG 3x, PNG 4x<br>• Generates icon verification report<br><br><strong>Why this matters:</strong><br>• Icons may look different when exported (especially SVGs)<br>• Gradients, filters, or effects may not export correctly<br>• Ensures visual consistency between design and code<br><br><strong>⚠️ Trade-offs:</strong><br>• Adds 10-30 seconds per icon batch<br>• Makes additional Figma API requests for screenshots<br>• May retry failed icons multiple times<br><br><strong>Benefits:</strong><br>• Higher icon accuracy with automatic retries<br>• Catches export issues early<br>• Detailed verification reports<br><br><strong>✅ Recommended:</strong> Keep enabled for icon-heavy designs.",
            "default": true
          },
          "iconVerificationThreshold": {
            "title": "🔍 Icon Verification Threshold (%)",
            "minimum": 0,
            "maximum": 100,
            "type": "integer",
            "description": "Maximum acceptable visual difference percentage (0-100) for icon verification.<br><br><strong>How it works:</strong><br>• Each downloaded icon is compared with its Figma screenshot<br>• Difference calculated as percentage of mismatched pixels<br>• Icons exceeding threshold trigger retry with alternative settings<br><br><strong>Threshold guidelines:</strong><br>• <strong>5%</strong> = Very strict (exact match, may cause excessive retries)<br>• <strong>10%</strong> = Recommended (catches significant issues, tolerates minor rendering differences)<br>• <strong>15%</strong> = Moderate (allows more variation)<br>• <strong>20%+</strong> = Lenient (only catches major export failures)<br><br><strong>Common sources of variation:</strong><br>• SVG rendering differences (browser vs Figma)<br>• Anti-aliasing differences at small sizes<br>• Color space conversions<br>• Path rounding differences<br><br><strong>⚠️ Note:</strong> Higher thresholds reduce retry attempts but may accept lower-quality icons.<br><br><strong>✅ Recommended:</strong> Use 10% for balanced icon quality.",
            "default": 10
          }
        }
      },
      "runsResponseSchema": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "actId": {
                "type": "string"
              },
              "userId": {
                "type": "string"
              },
              "startedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "finishedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "status": {
                "type": "string",
                "example": "READY"
              },
              "meta": {
                "type": "object",
                "properties": {
                  "origin": {
                    "type": "string",
                    "example": "API"
                  },
                  "userAgent": {
                    "type": "string"
                  }
                }
              },
              "stats": {
                "type": "object",
                "properties": {
                  "inputBodyLen": {
                    "type": "integer",
                    "example": 2000
                  },
                  "rebootCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "restartCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "resurrectCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "computeUnits": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "options": {
                "type": "object",
                "properties": {
                  "build": {
                    "type": "string",
                    "example": "latest"
                  },
                  "timeoutSecs": {
                    "type": "integer",
                    "example": 300
                  },
                  "memoryMbytes": {
                    "type": "integer",
                    "example": 1024
                  },
                  "diskMbytes": {
                    "type": "integer",
                    "example": 2048
                  }
                }
              },
              "buildId": {
                "type": "string"
              },
              "defaultKeyValueStoreId": {
                "type": "string"
              },
              "defaultDatasetId": {
                "type": "string"
              },
              "defaultRequestQueueId": {
                "type": "string"
              },
              "buildNumber": {
                "type": "string",
                "example": "1.0.0"
              },
              "containerUrl": {
                "type": "string"
              },
              "usage": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "integer",
                    "example": 1
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "usageTotalUsd": {
                "type": "number",
                "example": 0.00005
              },
              "usageUsd": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "number",
                    "example": 0.00005
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}