---
name: figma-to-static
description: >
Convert Figma design files to pixel-level mobile-first static HTML/CSS pages.
Use when: (1) user provides a Figma file link and wants a static web page,
(2) user sends design screenshots/assets and says "按设计图还原",
(3) user asks to build a landing page from Figma,
(4) iterating on Figma-to-code pixel accuracy.
Handles: Figma MCP-first extraction (metadata/context/screenshots) with REST API fallback,
layered DOM reconstruction (not whole-image paste), visual diff pipeline with region heatmap for
quality validation, mobile-first responsive layout.
NOT for: React/Vue/SPA frameworks, server-side rendering, interactive JS-heavy pages.
metadata: {"clawdbot":{"emoji":"🎨","requires":{"bins":["python3"],"env":["FIGMA_MCP_TOKEN","FIGMA_TOKEN"]},"configPaths":["~/.claude/.credentials.json"]}}
---
# Figma → Static HTML/CSS
## Recommended Runtime Profile
- **Preferred model:** `anthropic/claude-opus-4-6`
- **Preferred thinking level:** `high`
- Use this profile for full-page restoration, asset extraction planning, and multi-section iteration.
- If only doing quick environment checks or tiny CSS tweaks, lower-cost models are acceptable.
## MCP Auth Non-Negotiables
When handling Claude/Figma MCP authentication, follow these rules with zero improvisation:
1. Keep **exactly one live auth session**.
2. Never start a second Claude/Figma auth flow until the first one is explicitly killed or succeeds.
3. Never manually retype or reconstruct long OAuth URLs in chat.
4. In remote/chat/headless handoff, prefer receiving **Authentication Code (`code#state`)** over full callback URL.
5. Use full callback URL only for **state-mismatch diagnostics** or localhost redirect recovery.
6. Treat vague confirmations (`done` / `好了` / `完成` / `ok`) as invalid auth evidence.
7. After Claude login succeeds, do **not** assume Figma MCP is authenticated; verify separately.
8. If a state/session mismatch is suspected, **stop immediately**, kill stale flow(s), and restart from one clean session.
## Remote Chat Handoff Rule
In chat/remote/headless environments:
- Prefer asking the user to return **`code#state`**.
- Request the **full callback URL** only when debugging state mismatch or localhost redirect failures.
- If the CLI already displayed an authorize URL, copy it exactly from tool output or extract it with `scripts/extract_auth_url.py`; never hand-retype long URLs.
- Before opening a fresh login flow, run `scripts/auth_session_guard.py` to detect conflicts or stale state.
- **Do not ask the user for `code#state` until REPL state is explicitly verified as `waiting-for-code`.**
- Scrape the current REPL output.
- Classify it with `python3 scripts/claude_repl_state.py --stdin`.
- Only if `safeForCodeSubmission=true`, lock the auth URL/state and ask the user for code.
## Abort Conditions
Stop immediately and explain the issue if any of the following is true:
- another live Claude auth/login process already exists
- callback/code belongs to an older session
- callback `state` does not match the active auth `state`
- a previous auth session is still waiting for input
- an OAuth URL appears truncated, wrapped, or whitespace-corrupted
When an abort condition is met, do **not** “try one more thing” inside the same flow. Kill or abandon stale session(s), start one clean session, and ask for only one auth artifact.
## Auth Status Reply Template
During auth, report progress in this shape:
- 阶段:`Claude 登录` / `Figma MCP 配置` / `Figma MCP 授权` / `MCP 工具验证`
- 状态:`成功` / `阻塞` / `需用户操作`
- 原因:一句话具体原因
- 下一步:一句话具体动作
- 需要用户提供:`code#state` / `callback URL` / `nothing`
## Constraints
- **Only native HTML + CSS.** No React, Vue, or any framework.
- **Mobile-first.** PC: centered `max-width`, background stretches.
- **Directory structure:** `assets/ css/ html/`
- **Layered UI structure.** Never paste a whole section as a single `
` unless the design element is truly an image (photo/illustration). Text, buttons, status indicators → real DOM. **Navigation bars and menus must always be real DOM** — they need to align with content width and have interactive states.
- **MCP screenshots for component images only.** Use MCP `get_screenshot` for visual assets (video covers, banners, illustrations). Use MCP `get_design_context` for components that need real DOM (nav, menus, footers) — it returns structured data with asset URLs for individual icons/logos.
- **Avoid absolute positioning.** Prefer `flexbox`, `grid`, `margin`, `padding`, and normal document flow. Only use `position: absolute` as last resort (e.g., decorative badges on cards, small floating labels).
- **Image dimensions must be declared.** Every `
` must have explicit `width`/`height` attributes or CSS `aspect-ratio` to prevent layout shift (CLS).
- **BEM-like semantic class names.** Use `.block__element--modifier` (e.g. `.signin-card__label`, `.hero-topbar__brand`). Never use `.s1`, `.btn2`, `.c-red` abbreviations.
- **1:1 pixel-level restoration target.** Use visual diff pipeline to validate.
## Multi-Page Strategy
- If the user specifies multiple pages (e.g., "首页 + 活动页 + 个人中心"), create separate HTML files: `html/index.html`, `html/activity.html`, `html/profile.html`, etc.
- If the user does not specify, **default to single page** (`html/index.html`).
- Each page shares the same `css/styles.css` and `assets/` directory.
- If Figma file has multiple pages (top-level Page nodes), ask user which pages to implement.
## Version Control
- **Commit after each completed section** (not after every CSS tweak).
- Commit message format: `feat: add section` or `fix: adjust `
- **Never push** unless user explicitly asks.
- Small, reversible commits. If unsure about a change, commit current state first, then experiment.
## Completion Criteria
The page is "done" when ALL of the following are met:
1. **Layout confirmed** by user (skeleton step).
2. **All sections implemented** with real DOM and real assets (no placeholders).
3. **Visual diff similarity ≥ 90%** against the full-page design reference.
4. **No horizontal scroll** on mobile viewport (375px-414px test).
5. **User explicitly confirms** final result.
6. **If custom generation rules were provided**, output satisfies those rules.
## Workflow
### 0. Environment Check
Check Figma access in strict priority order (**must attempt MCP first**):
**Priority 1 (required first attempt): Claude CLI + Figma MCP**
```bash
# Explicit token mode (recommended)
export FIGMA_MCP_TOKEN=...
python3 scripts/fetch_figma_mcp.py --action tools
# OR opt-in read from Claude credential file
python3 scripts/fetch_figma_mcp.py --allow-claude-credentials --action tools
```
- Lists tools → MCP authenticated, proceed with MCP workflow.
- If it fails with "No Figma MCP token found", **must first try one-click bootstrap**:
- `bash scripts/setup_claude_mcp.sh`
- safe default = preflight/status only; does **not** auto-start a login flow
- explicit opt-in to start login: `bash scripts/setup_claude_mcp.sh --start-login`
- Before any fresh login flow, run:
- `python3 scripts/auth_session_guard.py --mode claude-login`
- if a user-facing authorize URL is created, immediately persist the active state:
- `python3 scripts/claude_auth_lock.py acquire --session-id --auth-url ""`
- In remote/chat/headless environments, prefer **one persistent `claude` REPL session** over repeated `claude auth login` attempts.
- Login rule: once a Claude auth prompt has produced an authorize URL, **do not create a second login flow** until the first one either succeeds or is explicitly abandoned.
- During remote/chat handoff, ask for **Authentication Code (`code#state`) first**.
- Before asking for it, prove the REPL is actually waiting for code:
- scrape current terminal output
- classify with `python3 scripts/claude_repl_state.py --stdin`
- proceed only when `state=waiting-for-code` and `safeForCodeSubmission=true`
- Request full callback URL only for stale-state diagnostics or localhost redirect failures:
- `https://platform.claude.com/oauth/code/callback?code=...&state=...`
- Do **not** accept only "好了/完成/ok" as auth completion signal.
- If one-click bootstrap is unavailable, use manual onboarding:
1. Install Claude CLI: `npm install -g @anthropic-ai/claude-code`
2. Login:
- **Local interactive shell:** try `claude auth login`
- **Remote/headless/chat handoff (preferred):** run `claude`, then `/login`, keep that same REPL session alive, and paste Authentication Code (`code#state`) when prompted.
- Do **not** bounce between `claude auth login` and `claude` REPL during the same auth attempt.
3. Add server: `claude mcp add --scope user --transport http figma https://mcp.figma.com/mcp`
4. Open Claude UI and finish MCP auth in **one session**:
- run `claude`
- run `/mcp`
- select `figma` and complete Authenticate/Connect flow
- if Figma browser redirects to localhost and fails, paste the **full localhost callback URL** back into Claude
5. Verify: `claude mcp list` (expect `figma ... Connected`)
- After step 5, retry `python3 scripts/fetch_figma_mcp.py --allow-claude-credentials --action tools`.
- See `references/figma-mcp-usage.md` for details.
**Priority 2: Figma REST API** (fallback, detailed CSS properties)
```bash
curl -s -o /dev/null -w "%{http_code}" \
-H "X-Figma-Token: $FIGMA_TOKEN" \
"https://api.figma.com/v1/me"
```
- **200** → Token valid. Use quota-aware REST mode first:
- `python3 scripts/fetch_figma_rest.py --file-key FILE_KEY --nodes "NODE1,NODE2" --quota-aware --batch-size 3 --max-retry-after 60`
- **401/403** → Guide user to generate token at Figma → Account Settings → Personal access tokens.
- **429** → Do not tight-retry. Reduce batch size (`--batch-size 1~2`) or switch to `--metadata-only` skeleton flow.
**Priority 3: User-provided assets** (fallback)
- ZIP of design assets + design screenshots.
### Quick Troubleshooting
Before troubleshooting remote/chat/headless MCP auth, read:
- `references/mcp-auth-state-machine.md`
When MCP is not ready, guide the user in this exact order:
Auth policy while replying:
- be terse and procedural
- do not improvise or summarize partial auth as success
- do not reassure unless a verification command passed
- always state: current stage, blocker, exact next action, exact artifact needed from user
1. **One-click setup (recommended first, default path)**
- Run a single command:
- `bash scripts/setup_claude_mcp.sh`
- Preflight guard (must pass before new flow):
- `python3 scripts/auth_session_guard.py --mode claude-login`
- This script handles: install Claude CLI → login preflight → add figma MCP → status verification.
- Safe default: it does **not** auto-start a fresh login flow.
- Start login only with explicit opt-in:
- `bash scripts/setup_claude_mcp.sh --start-login`
- If an authorize URL is generated, persist the active state before asking the user for auth data:
- `python3 scripts/claude_auth_lock.py acquire --session-id --auth-url ""`
- In remote/headless/chat flows, prefer **one persistent `claude` REPL session**:
- run `claude`
- complete any first-run setup screens first (theme / login method)
- scrape the visible REPL output and classify with `python3 scripts/claude_repl_state.py --stdin`
- if state is not `waiting-for-code`, do not ask user for auth data yet
- run `/login` if needed
- open the authorize URL shown by Claude
- if you need to pass the URL through chat, first extract it exactly with `python3 scripts/extract_auth_url.py --stdin`
- persist the active state via `python3 scripts/claude_auth_lock.py acquire --session-id --auth-url ""`
- paste Authentication Code (`code#state`) into `Paste code here if prompted >`
- keep that same Claude session alive until login succeeds
- Reject vague confirmations ("好了/完成"). Require exact auth handoff text (`code#state`, callback URL, or localhost callback URL).
- Before asking for auth data, classify the live REPL output with `python3 scripts/claude_repl_state.py --stdin`; only continue when it reports `waiting-for-code`.
- Validate user-returned auth data against the active lock **before** submission:
- `python3 scripts/claude_auth_lock.py verify-code --code-state ""`
- or `python3 scripts/claude_auth_lock.py verify-callback --callback-url ""`
- **Never** start another login attempt while one Claude session is already waiting for callback/code.
2. **Check Claude usage quota early (avoid dead-end loops)**
- Quick probe:
- `claude --print "quota-check"`
- If output contains phrases like `You've hit your limit` / reset time:
- Stop MCP auth retry loop (this is quota, not auth wiring)
- Wait for reset, or switch/upgrade Claude account
- Continue delivery via REST fallback (`FIGMA_TOKEN`) with skeleton-first + quota-aware pulling
3. **If one-click setup fails, use manual checks**
- Follow `references/mcp-auth-state-machine.md` strictly; do not improvise auth retries.
- `claude` command not found:
- `npm install -g @anthropic-ai/claude-code`
- Re-check: `claude --version`
- Not logged in:
- local shell: `claude auth login`
- remote/headless/chat: `claude` → `/login` → keep the same REPL alive → paste Authentication Code (`code#state`)
- Figma MCP server missing:
- `claude mcp add --scope user --transport http figma https://mcp.figma.com/mcp`
- Figma MCP shows `Needs authentication`:
- open `claude` → `/mcp` → figma → Authenticate/Connect
- if browser redirects to localhost and fails, paste the full localhost callback URL back into the same Claude session
- verify with `claude mcp list` (must be `Connected`)
4. **Script cannot find token**
- Preferred explicit mode:
- `export FIGMA_MCP_TOKEN=...`
- `python3 scripts/fetch_figma_mcp.py --action tools`
- Optional credential-file mode:
- `python3 scripts/fetch_figma_mcp.py --allow-claude-credentials --action tools`
5. **Still blocked after MCP auth is truly stabilized**
- Do **not** recommend PAT/REST just because Claude auth handoff was messy once.
- First confirm all of the following:
- `claude auth status` shows logged in
- `claude mcp list` shows `figma ... Connected`
- the MCP `whoami` result matches the intended Figma account
- only then test `fetch_figma_mcp.py`
- Only if MCP is authenticated yet the target file remains inaccessible or the user explicitly wants fallback, use REST API mode (quota-aware, low burst):
- `export FIGMA_TOKEN=...`
- `python3 scripts/fetch_figma_rest.py --file-key FILE_KEY --nodes "NODE1,NODE2" --quota-aware --batch-size 2 --sleep-ms 1500 --max-retry-after 60`
- If 429 persists with long `Retry-After`, stop image pull and continue with metadata-only skeleton:
- `python3 scripts/fetch_figma_rest.py --file-key FILE_KEY --nodes "NODE1,NODE2" --metadata-only`
- Or continue with user-provided ZIP/screenshots.
6. **Callback invalid / stale diagnostics (must check before retry loop)**
- Most common causes:
1) stale callback from an older auth attempt (state mismatch)
2) multiple concurrent `claude auth login` sessions created different states
3) waiting login process was terminated (timeout/SIGTERM) before callback handoff
4) authorize URL was copied through chat with truncation/whitespace corruption
- Enforce single-session rule: keep only one active Claude login process at a time.
- Run guard first:
- `python3 scripts/auth_session_guard.py --mode claude-login`
- Extract the authorize URL from raw CLI output instead of hand-copying:
- `python3 scripts/extract_auth_url.py --stdin`
- Validate callback state against current authorize URL:
- `python3 scripts/parse_claude_oauth_callback.py --auth-url "" --callback-url ""`
- If mismatch, stop immediately, kill stale flow(s), and use **only one new authorize URL**.
### 0.3 Validate Figma Link (must run before rule intake)
Before asking custom rules, validate link/file/node first:
```bash
# Fast syntax check (no token required)
python3 scripts/validate_figma_input.py --figma-url ""
# Strong check (requires FIGMA_TOKEN): verify file accessibility + full-page heuristic
FIGMA_TOKEN=... python3 scripts/validate_figma_input.py --figma-url "" --check-api
```
Decision rules:
- `INVALID_URL` / `FILE_INVALID_OR_UNAUTHORIZED` / `NODE_INVALID` → stop and ask user for corrected link/access.
- `FULL_PAGE_ASSESSMENT: likely partial/component` → ask user to confirm whether they want component restore or provide page-level node-id.
- If no `node-id`, default target is whole file/page and continue.
### 0.5 Rule Intake Gate (Optional, Can Be Empty)
Before generating code, offer user an optional rule intake. If user leaves it blank, proceed with defaults.
Collect only these six fields:
1. **Adaptive strategy**
- User options: `mobile-first` / `desktop-first` / `mobile-only` / `desktop-only`
- Default: `mobile-first`
2. **Breakpoints**
- User format example: `375, 768, 1200`
- Default: `375, 768, 1200`
3. **Layout width strategy**
- User options: `fixed width` / `fluid` / `max-width centered`
- Default: `max-width centered`
4. **Typography sizing strategy**
- User options: `px` / `rem` / `clamp`
- Default: `clamp` for responsive text, with pixel-accurate base ratio
5. **Interactive states**
- User options: `none` / `basic` (`:hover,:active,:disabled`) / `full`
- Default: `basic`
6. **Browser compatibility target**
- User options: `modern evergreen only` / `include Safari stable`
- Default: `include Safari stable`
If any field is empty, keep the default and continue execution without blocking.
Quick prompt template:
```text
可选自定义生成规则(可留空,留空=默认):
1) 端适配策略(mobile-first/desktop-first/mobile-only/desktop-only):
2) 断点(例如 375,768,1200):
3) 页面宽度策略(fixed/fluid/max-width centered):
4) 字体策略(px/rem/clamp):
5) 交互态(none/basic/full):
6) 浏览器兼容目标(modern only/include Safari stable):
```
### 1. Gather Inputs
Required (at least one):
- Figma file URL + fileKey
- User-provided ZIP of design assets (PNG/SVG)
- Design reference screenshots
**If Figma MCP available** (preferred):
```bash
# Choose auth mode once:
# A) export FIGMA_MCP_TOKEN=...
# B) MCP_AUTH="--allow-claude-credentials"
# Step 1: Batch pull metadata+screenshot+context in one MCP session
python3 scripts/fetch_figma_mcp.py ${MCP_AUTH:-} \
--file-key FILE_KEY \
--node-ids "NODE_ID NAV_NODE_ID COVER1 COVER2" \
--action bundle \
--out-dir ./mcp-assets
# Step 2: Parse/download context assets automatically (SVG normalization included)
python3 scripts/parse_design_context.py \
--context-glob "./mcp-assets/context-*.txt" \
--assets-dir ./assets \
--manifest ./source/context-assets.json
# Step 3: Optional targeted screenshots for image-heavy sections
python3 scripts/fetch_figma_mcp.py ${MCP_AUTH:-} \
--file-key FILE_KEY \
--node-ids "BANNER1 FOOTER" \
--action screenshot \
--out-dir ./assets
```
**If REST API available** (for detailed CSS extraction):
- First run quota-aware small-batch pull:
- `python3 scripts/fetch_figma_rest.py --file-key FILE_KEY --nodes "NODE1,NODE2" --quota-aware --batch-size 2 --sleep-ms 1500 --max-retry-after 60`
- If image quota is blocked, switch to skeleton-safe metadata mode:
- `python3 scripts/fetch_figma_rest.py --file-key FILE_KEY --nodes "NODE1,NODE2" --metadata-only`
- Then run `scripts/figma_to_css.py` on the exported `nodes.json`.
**If ZIP provided:**
- Unzip to `source/`, rename files meaningfully, copy usable assets to `assets/`.
### 2. Analyze Structure → Layout First, Then Details
**Critical rule: always build the skeleton before polishing pixels.**
1. **Identify sections** from the full-page design:
- Scan top-to-bottom, name each visual block (hero, signin, feature-1, feature-2, footer…).
- Output a section map with approximate vertical order and height ratios.
2. **Build the skeleton** — placeholder-only HTML/CSS:
- One `` per block with a colored background or placeholder text.
- Flex/grid layout structure in place (no absolute positioning).
- Correct vertical stacking order and relative heights.
- `overflow-x: hidden` on body, scrollable rows marked.
3. **Take skeleton screenshot → send to user for confirmation.**
- Ask: "布局结构和分段顺序对吗?"
- Do NOT proceed to detail work until user confirms the layout.
4. **Layer in details** per confirmed section:
- Insert real assets (images, icons).
- Build real DOM for text, buttons, status indicators, timelines.
- Apply typography, colors, spacing, borders from Figma node data.
- Take screenshot → send to user after each section completes.
- Git commit after each section is done.
6. **Missing assets? Try to fetch before asking:**
- Check if the asset exists in `assets/` or `source/` (cache first).
- If REST API is available, pull only the needed nodes in small batches:
- `python3 scripts/fetch_figma_rest.py --file-key FILE_KEY --nodes "" --quota-aware --batch-size 1`
- If the node ID is unknown, ask the user for the specific layer/node ID.
- If REST API quota is blocked (`quota-status.json` shows degraded), continue skeleton and ask user for direct asset file.
7. **NEVER generate fake assets.**
- Do NOT screenshot a design and crop it to create an "asset".
- Do NOT draw/create placeholder images to simulate missing design elements.
- Do NOT use solid-color boxes or emoji to stand in for real icons/photos.
- Every pixel must come from either: (a) Figma export, (b) user-provided file, or (c) CSS/SVG reconstruction of simple shapes (borders, backgrounds, gradients — NOT complex illustrations).
### 3. Build the Page
First apply resolved rule-intake profile (user values or defaults), then generate files.
Generate three directories:
**`html/index.html`** (or `html/.html` for multi-page)
- Semantic `` per design block.
- Real DOM elements for text, status, buttons, timelines.
- Images only for true visual assets (backgrounds, illustrations, photos).
- `` with `width=device-width, initial-scale=1`.
**`css/styles.css`**
- `:root` variables for max-width and theme colors.
- `overflow-x: hidden` on `html, body, .page-shell` to prevent horizontal scroll.
- `overflow-x: clip` on `.stage` containers; only specific scrollable rows get `overflow-x: auto`.
- Percentage-based positioning for overlays (derived from Figma node coordinates).
- `clamp()` for responsive typography.
- `@media (min-width: 801px)` for PC centered layout.
**`assets/*`**
- Named meaningfully (not `figma-01.png`).
- Prefer user-provided assets over Figma exports when available.
### 4. Auto-Extract CSS from Figma Nodes
After fetching `nodes.json`, run the auto-extraction script:
```bash
python3 scripts/figma_to_css.py --nodes rest-assets/nodes.json --out source/figma-extracted.css
```
This parses every node and outputs CSS property blocks for:
- Colors, fonts, spacing, shadows, borders, border-radius
- Auto-layout: flex-direction, gap, justify-content, align-items, padding
Use the extracted CSS as a reference when writing `styles.css`. Do NOT copy-paste blindly — adapt to the actual DOM structure.
### 5. Extract Exact Properties from Figma Nodes
**Do not guess.** Read `nodes.json`, then map values to CSS.
Use this reference for full mapping table + strict rules:
- `references/css-extraction-rules.md`
### 6. Visual Diff Validation (with Region Heatmap)
After each major iteration:
```bash
# 1. Screenshot current render
google-chrome --headless=new --disable-gpu --no-sandbox \
--window-size=800,5338 \
--screenshot=compare/current.png \
http://127.0.0.1:PORT/html/
# 2. Compare with region heatmap + structure metrics (default 5x5 grid)
python3 scripts/visual_diff.py \
--current compare/current.png \
--target assets/design-main.png \
--diff compare/diff.png \
--regions 5 \
--threshold 30 \
--json-out compare/metrics.json
```
The tool outputs:
- **MAE similarity** (pixel-level)
- **SSIM similarity** (structure-level)
- **Composite similarity** (weighted MAE + SSIM)
- Heatmap overlay (green/yellow/red), plus labeled bad regions by MAE threshold
Focus iteration on red regions first, then raise composite similarity.
### 7. Preview Server
When running on a cloud server, start a temporary HTTP server for public preview:
```bash
# Find an available port (e.g. 8090 if 8080 is taken)
python3 -m http.server PORT --bind 0.0.0.0
```
- Run in background so it persists across iterations.
- Bind to `0.0.0.0` (not `127.0.0.1`) so it's accessible via public IP.
- Check for port conflicts before starting (`lsof -i :PORT` or `ss -tlnp`).
- Provide user with `http://:PORT/html/` link.
- If running behind a firewall, ensure the port is open.
### 8. Screenshot & Send to User (Every Iteration)
After each code generation iteration, before reporting results:
1. Take a screenshot of the current render:
```bash
google-chrome --headless=new --disable-gpu --no-sandbox \
--window-size=800,5338 \
--screenshot=compare/current.png \
http://127.0.0.1:PORT/html/
```
2. **Send the screenshot to the user** via the messaging platform (Telegram/Discord/etc.) using the media/file sending tool — do NOT just send a URL, send the actual image.
3. Then optionally run visual diff against target and mention the similarity score.
This ensures the user can verify visual quality **without opening a browser** on every iteration.
## Anti-Patterns (Shortlist)
1. Never use a full-section screenshot when real DOM is required.
2. Never invent content or fake assets.
3. Never skip mobile overflow controls (`overflow-x: hidden` where needed).
4. Never guess properties that exist in Figma JSON.
5. Never build nav/menu/timeline as image slices when interactive DOM is expected.
Full checklist: `references/anti-patterns.md`
## Scripts
- `scripts/validate_figma_input.py` — Validate Figma URL/file/node; optionally classify whether target is full-page vs component (`--check-api`).
- `scripts/fetch_figma_mcp.py` — **Primary.** MCP fetcher with token auto-refresh, batch node extraction (`--node-ids`), and bundle mode (`--action bundle`).
- `scripts/auth_session_guard.py` — Detect conflicting Claude sessions and refuse fresh login attempts while an active auth lock or existing Claude process is present.
- `scripts/claude_auth_lock.py` — Persist the one active Claude auth state (`sessionId` + authorize URL/state) and validate incoming `code#state` or callback URLs before submission.
- `scripts/claude_repl_state.py` — Classify raw Claude REPL output (theme picker / login method picker / waiting-for-code / ambiguous) and block auth handoff unless the REPL is actually waiting for code.
- `scripts/extract_auth_url.py` — Extract an unbroken Claude OAuth authorize URL from raw terminal output; use instead of hand-copying wrapped URLs.
- `scripts/parse_claude_oauth_callback.py` — Validate callback URL or `code#state` against the active authorize URL to detect stale/invalid callbacks.
- `scripts/parse_design_context.py` — Parse MCP context files, download asset URLs, and normalize SVG stretch issues.
- `scripts/fetch_figma_rest.py` — Extract node metadata + images via Figma REST API (needs `FIGMA_TOKEN`), with quota-aware batching, retry-after guardrail, metadata-only degradation, and local cache reuse.
- `scripts/figma_to_css.py` — Auto-parse REST `nodes.json` → CSS property blocks.
- `scripts/visual_diff.py` — Compare render vs target with MAE + SSIM + heatmap.
## References
- `references/figma-mcp-usage.md` — Figma MCP tools reference, setup, auth modes, and batch usage.
- `references/css-extraction-rules.md` — Strict property mapping and non-negotiable CSS extraction rules.
- `references/file-structure.md` — Standard project directory layout.
- `references/css-patterns.md` — Reusable CSS patterns for common design elements.
- `references/anti-patterns.md` — Full anti-pattern checklist for QA passes.