# Figma Sync

> Sync Figma design content to local storage, export assets to Xcode, and maintain Figma-to-Task mapping. Use when the user mentions Figma sync, design export, pixel-perfect, design-to-code, updating design references from Figma, or comparing implementation against Figma design.

- Skill: `rayliu66/figma-sync` (Agent Skill, multi-file: 5 files)
- Install (CLI): `npx skillmds@latest add rayliu66/figma-sync`
- Raw SKILL.md: https://api.skillmd.com/api/skills/rayliu66/figma-sync/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Design & Media
- Author: Rayliu66 (https://skillmd.com/u/rayliu66)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/rayliu66/figma-sync

---


# Figma Sync Workflow (Figma-WF)

Repeatable workflow for syncing Figma designs to local cache and Xcode assets. Follows PM-WF 1.8 format.

## Project Config

| Key | Value |
|-----|-------|
| Figma file key | `tZhdm3G4gxrUrXsTK6iPYh` |
| Figma root node | `0:1` |
| Figma MCP server | `user-Figma` |
| Local cache dir | `{PROJECT_ROOT}/../../../figma/` (i.e. `Countdown Clock/figma/`) |
| Assets target | `Chrona/Assets.xcassets/` |
| Notion task DB | `3168d41a5cff80dd813cc84e79466003` |

## Workflow Overview

```mermaid
flowchart TD
    S0["Stage 0: Check for Changes"] --> NeedSync{"Changes detected?"}
    NeedSync -->|"No"| SkipDone["Done - No changes"]
    NeedSync -->|"Yes"| S1["Stage 1: Discover Figma Pages"]
    S1 --> S2["Stage 2: Export Design Context + Screenshots"]
    S2 --> CP1{"CP1: All pages exported?"}
    CP1 -->|"Incomplete"| S2
    CP1 -->|"Complete"| S3["Stage 3: Export Illustrations/Assets"]
    S3 --> S4["Stage 4: Generate Figma-Task Mapping"]
    S4 --> S5["Stage 5: Atomic Swap to Local"]
    S5 --> CP2{"CP2: Final Verification"}
    CP2 -->|"Failed"| S2
    CP2 -->|"Passed"| Done["Done - Ready for Dev"]
```

## Incremental Update Strategy

Figma has NO per-node timestamps. Only file-level `lastModified` exists.

**Tier 1 -- File-level gate:**
Read `figma/sync-state.json`. If `lastModified` unchanged since last sync, skip entirely (zero MCP calls).

**Tier 2 -- Node-level metadata hash:**
If file changed, call `get_metadata` on root (1 MCP call). Hash each node's metadata (name, type, position, size, child count). Compare against hashes in `sync-state.json`. Only re-export nodes whose hash changed.

**Limitation:** Metadata hash misses pure visual changes (e.g. color swap without structural change). Use `--force` flag or periodic full sync for those.

## MCP Tool Quick Reference

### get_metadata
```json
{
  "server": "user-Figma",
  "toolName": "get_metadata",
  "arguments": { "fileKey": "tZhdm3G4gxrUrXsTK6iPYh", "nodeId": "0:1" }
}
```
Returns: Sparse XML with layer IDs, names, types, positions, sizes. Use to enumerate pages and detect structural changes.

### get_design_context
```json
{
  "server": "user-Figma",
  "toolName": "get_design_context",
  "arguments": { "fileKey": "tZhdm3G4gxrUrXsTK6iPYh", "nodeId": "{PAGE_NODE_ID}" }
}
```
Returns: Code reference (React+Tailwind default), screenshot, design tokens, contextual hints. Primary tool for extracting design details.

### get_screenshot
```json
{
  "server": "user-Figma",
  "toolName": "get_screenshot",
  "arguments": { "fileKey": "tZhdm3G4gxrUrXsTK6iPYh", "nodeId": "{NODE_ID}" }
}
```
Returns: High-res screenshot of the specified node. Use for page-level screenshots and individual asset exports.

## Stage 0: Check for Changes

1. Read `figma/sync-state.json` (create empty state if not found)
2. Call `get_metadata` on root node `0:1`
3. Compare file `lastModified` against stored value
4. If unchanged: **STOP** -- print "No changes detected" and exit
5. If changed or first sync:
   - Parse metadata XML to extract all top-level nodes
   - Compute SHA-256 hash of each node's metadata string
   - Compare against stored hashes
   - Build `changedNodes[]` list (or all nodes if first sync)
6. If `--force` flag: treat all nodes as changed

**Checklist:**
- [ ] sync-state.json read (or initialized)
- [ ] get_metadata called on root
- [ ] lastModified compared
- [ ] Changed nodes identified

## Stage 1: Discover Figma Pages

1. From Stage 0 metadata, extract all top-level frames/pages
2. Build page index:
   ```
   | nodeId | Name | Status | Notion Task |
   |--------|------|--------|-------------|
   | 0:1    | Home | changed | F1         |
   | ...    | ...  | ...     | ...        |
   ```
3. Map each page to corresponding Notion task (F1-F10) by name matching
4. Save index to `figma/.tmp/index.json`

**Checklist:**
- [ ] All top-level pages enumerated
- [ ] Each page mapped to Notion task
- [ ] Status (new/changed/unchanged) assigned
- [ ] index.json written to .tmp/

## Stage 2: Export Design Context + Screenshots

For each **changed** page (or all if full sync):

1. Call `get_design_context` with page's nodeId
2. Save response to `figma/.tmp/pages/{nodeId}/design-context.md`
3. Call `get_screenshot` with page's nodeId
4. Save screenshot to `figma/.tmp/pages/{nodeId}/screenshot.png`
5. Save raw metadata to `figma/.tmp/pages/{nodeId}/metadata.json`

For **unchanged** pages: copy from existing `figma/pages/{nodeId}/` to `.tmp/pages/{nodeId}/`

**Rate limit handling:**
- If MCP returns rate limit error, wait 60 seconds and retry
- Track progress in `figma/.tmp/export-progress.json`
- On retry, skip already-exported nodes
- After 3 consecutive failures, stop and report partial progress

**CP1 Checklist:**
- [ ] Every page in index has a directory in .tmp/pages/
- [ ] Each directory contains design-context.md, screenshot.png, metadata.json
- [ ] No errors in export-progress.json

## Stage 3: Export Illustrations / Custom Assets

1. For each changed page, parse `design-context.md` for illustration/image components
2. Identify nodes that are custom illustrations (not system icons)
3. For each illustration node:
   - Call `get_screenshot` at 2x scale
   - Call `get_screenshot` at 3x scale
   - Save to `figma/.tmp/assets/{name}/`
   - Generate `Contents.json` for Xcode imageset:
     ```json
     {
       "images": [
         { "filename": "{name}@2x.png", "idiom": "universal", "scale": "2x" },
         { "filename": "{name}@3x.png", "idiom": "universal", "scale": "3x" }
       ],
       "info": { "author": "figma-sync", "version": 1 }
     }
     ```

**Checklist:**
- [ ] All illustration nodes identified
- [ ] 2x and 3x PNGs exported
- [ ] Contents.json generated per imageset
- [ ] Assets ready for Assets.xcassets copy

## Stage 4: Generate Figma-Task Mapping

Generate `figma/.tmp/FIGMA_MAPPING.md` using the template in [mapping-template.md](mapping-template.md).

Three sections:
1. **Page-to-Task mapping** -- Figma page nodeId to Notion task (F1-F10)
2. **Component-to-Swift mapping** -- Figma component to Swift source file
3. **Design token comparison** -- Figma values vs `DesignTokens.swift` values

For design token comparison:
- Extract colors, fonts, spacing from `get_design_context` responses
- Read current `Chrona/Design/DesignTokens.swift`
- Compare and flag mismatches

**Checklist:**
- [ ] All pages mapped to Notion tasks
- [ ] Components mapped to Swift files
- [ ] Design tokens compared
- [ ] Mismatches flagged with specific values

## Stage 5: Atomic Swap to Local

Only execute after CP1 passes (all exports successful).

1. If `figma/` directory exists:
   - Create backup: `mv figma/ figma/.backup-{YYYYMMDD-HHmmss}/`
2. Create fresh `figma/` directory
3. Move from `.tmp/`:
   - `figma/.tmp/pages/` -> `figma/pages/`
   - `figma/.tmp/assets/` -> `figma/assets/`
   - `figma/.tmp/index.json` -> `figma/index.json`
   - `figma/.tmp/FIGMA_MAPPING.md` -> `figma/FIGMA_MAPPING.md`
4. Copy each asset imageset to `Chrona/Assets.xcassets/`:
   - `figma/assets/{name}/` -> `Chrona/Assets.xcassets/{name}.imageset/`
5. Write updated `figma/sync-state.json` with new lastModified and node hashes
6. Remove `figma/.tmp/` directory
7. Remove backups older than 7 days

**Rollback:** If any step 2-6 fails, restore from `.backup-{timestamp}/`

**CP2 Final Checklist:**
- [ ] figma/pages/ has all page directories
- [ ] figma/assets/ has all illustration imagesets
- [ ] figma/index.json lists all pages
- [ ] figma/FIGMA_MAPPING.md is complete
- [ ] figma/sync-state.json updated
- [ ] Assets.xcassets/ has new imagesets
- [ ] .tmp/ directory removed
- [ ] No errors during swap

## Usage

### Full Sync (First Time)
```
User: "Sync all Figma designs to local"
```
Agent reads this skill, executes Stage 0-5 with all nodes.

### Incremental Sync
```
User: "Update Figma designs"
```
Agent reads this skill, executes Stage 0 gate, only re-exports changed nodes.

### Force Full Sync
```
User: "Force full Figma sync"
```
Agent treats all nodes as changed, bypasses incremental gate.

### Single Page Sync
```
User: "Sync Figma page for Home Screen"
```
Agent runs Stage 0, then only exports the matching page node.

## Additional Resources

- For detailed stage prompts and MCP examples, see [reference.md](reference.md)
- For FIGMA_MAPPING.md template, see [mapping-template.md](mapping-template.md)
- For sync-state.json schema, see [sync-state-schema.json](sync-state-schema.json)

