Skip to content

Commit aff3c88

Browse files
rubenmarcusclaude
andauthored
feat: enhance Figma integration with full API property coverage (#251)
* feat: expose --max-cost CLI flag with cost threshold warnings Wire the existing maxCost infrastructure to a new --max-cost CLI option. When no budget is set, warn users at $2/$5/$10 thresholds to encourage setting a limit. This is opt-in only — no default limit that could break existing long-running loops. Closes #211 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add Figma-specific agent prompts in context builder When sourceType is 'figma', inject domain-specific guidelines into the agent preamble: auto-layout to flexbox/grid mapping, color token extraction with @theme inline, typography fidelity, constraint conversion, responsive breakpoints, and placeholder images. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: auto-inject Figma design tokens and cap spec size When fetching from Figma in default 'spec' mode, also fetch design tokens (CSS variables) and prepend them to the spec. The agent gets ready-to-use tokens for @theme inline instead of parsing the raw tree. Also pass all Figma CLI options through to fetchFromSource (previously only label/status/limit/issue were passed). Cap in-prompt spec at 15KB to reduce token waste — full spec remains on disk in specs/ directory. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: show model name and cost in loop header and separator Display the model name (e.g. '3-sonnet') and cumulative cost in the loop header subtitle line, and add the full model name to the iteration separator. Users can now see what model is running and how much it costs at a glance. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * test: add context-builder and task-executor tests Add 42 new tests covering: - buildIterationContext: preamble content, Tailwind v4 guidance, iteration-aware trimming (full/abbreviated/minimal), plan rules, design quality guidelines, validation feedback, iteration log - compressValidationFeedback: truncation, section headers, ANSI stripping - buildTrimmedPlanContext: task info, subtasks, completion counts - buildCommitMessage: conventional commit detection (feat/fix/docs/ refactor/test/chore), prefix stripping (bracket and colon formats) - buildPrBody: task URL, description truncation, execution details Export buildCommitMessage and buildPrBody for testability. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: enhance Figma integration with full API property coverage Add ~20 missing Figma REST API properties to types, parsers, and agent guidelines for significantly improved design-to-code fidelity. Layout: layoutSizingHorizontal/Vertical (FIXED/HUG/FILL), layoutWrap, layoutPositioning (absolute children), counterAxisSpacing, layoutAlign, min/maxWidth/Height, clipsContent, scrollBehavior, overflowDirection. Visual: individualStrokeWeights (per-side borders), strokeDashes, rotation, isMask, imageTransform→object-position, image filters→CSS filter(), hero section detection, icon SVG export. Typography: fontStyle, textTruncation + maxLines with CSS line-clamp hints, hyperlink detection. Effects: progressive blur detection, backdrop-filter hints. New parsers: font-checker (Google Fonts validation), image-collector, icon-collector (VECTOR/INSTANCE node detection + SVG export). Agent guidelines updated with sizing, wrap, absolute positioning, overflow, sticky/fixed, borders, rotation, and image filter rules. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat: add universal design-to-code rules for z-index, image priority, and sequential patterns - Text/content elements always get higher z-index than visual layers (universal stacking rule) - Classify image semantic importance: person images are CRITICAL priority, never hidden at any breakpoint - Detect sequential/numbered patterns (01, 02, 03) in sibling elements, preserve exact design order - Add Universal Stacking & Layout Rules section to generated implementation plans - Add image-optimizer utility and plan-generator for Figma integration Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: prevent division-by-zero in imageTransformToObjectPosition Replace magic 0.99 threshold with epsilon-based comparison (1e-4) to eliminate the gap where values in [0.99, 1.0) could cause division by near-zero or inconsistent behavior. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: sanitize Figma asset filenames and validate CDN URLs Add sanitizeAssetFilename(), isValidFigmaCdnUrl(), and sanitizeSvgContent() utilities. Apply to all four Figma asset download locations in run.ts to prevent path traversal, SSRF, and SVG XSS attacks. Addresses GitHub Advanced Security review comments. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: harden security sanitization and eliminate TOCTOU races - Rewrite sanitizeSvgContent with iterative stripping for nested/malformed tags - Add PNG magic byte validation (isValidPngBuffer) for all image downloads - Remove existsSync checks before mkdirSync (TOCTOU race conditions) - Remove unused existsSync import from source.ts - Update pnpm-lock.yaml for sharp optional dependency Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: resolve remaining CodeQL security alerts - Rewrite sanitizeSvgContent with substring-based parser instead of regex to satisfy CodeQL js/bad-tag-filter and js/incomplete-multi-character-sanitization rules - Fix TOCTOU race in readCache using fd-based stat+read (openSync/fstatSync) - Fix TOCTOU race in image-optimizer using readFileSync buffer instead of separate statSync + sharp(filePath) calls Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent a43c8a9 commit aff3c88

24 files changed

Lines changed: 4319 additions & 126 deletions

docs/blog/2026-02-01-figma-to-code-one-command.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ $ ralph-starter run --from figma \
2222
--project "https://figma.com/file/ABC123/Dashboard" \
2323
--figma-mode components \
2424
--figma-framework react \
25-
--loops 5 --test --commit
25+
--max-iterations 5 --test --commit
2626

2727
🔄 Loop 1/5
2828
→ Fetching from Figma API... 12 frames, 34 components found
@@ -83,14 +83,28 @@ Setup is dead simple, just a personal access token from Figma:
8383
ralph-starter config set figma.token figd_xxxxx
8484
```
8585

86+
:::tip Figma Plan Matters
87+
The free/starter plan limits you to **6 API requests per month** -- that is barely one fetch. For real development, you need a **Professional plan with a Dev seat** ($12/month), which gives you 10+ requests per minute. Responses are cached locally so repeated runs are free.
88+
:::
89+
8690
The reason this works at all is [the loop](/blog/my-first-ralph-loop). The agent does not just generate code and stop. It generates, runs tests, sees what broke, fixes it, runs again. By loop 3 or 4 you have components that actually render and pass lint. Same [Ralph Wiggum technique](/blog/ralph-wiggum-technique) I use for everything else -- just pointed at a design file instead of a GitHub issue. I did not even plan it this way. It just... worked.
8791

8892
Want to try it with your own Figma file?
8993

9094
```bash
9195
npx ralph-starter init
9296
ralph-starter config set figma.token figd_your_token_here
93-
ralph-starter run --from figma --project "your-figma-url" --figma-mode components --figma-framework react --loops 5
97+
ralph-starter run --from figma --project "your-figma-url" --figma-mode components --figma-framework react --max-iterations 5
98+
```
99+
100+
You can also pick your model with `--model`. Sonnet is fast and cheap for UI work, Opus is better for complex state logic:
101+
102+
```bash
103+
# Fast + cheap (recommended for most Figma workflows)
104+
ralph-starter run --from figma --project "your-figma-url" --figma-mode components --model claude-sonnet-4-5-20250929 --max-iterations 5
105+
106+
# Maximum quality
107+
ralph-starter run --from figma --project "your-figma-url" --figma-mode components --model claude-opus-4-6 --max-iterations 3
94108
```
95109

96110
## References

docs/docs/sources/figma.md

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ Create a custom mapping file to control how Figma content maps to your component
199199
| `--figma-target` | Target directory (content mode) | Path (e.g., `src/pages`) |
200200
| `--figma-preview` | Preview without applying (content mode) | Flag |
201201
| `--figma-mapping` | Custom mapping file (content mode) | File path (e.g., `mapping.json`) |
202+
| `--model` | AI model for the coding agent | Model ID (e.g., `claude-sonnet-4-5-20250929`) |
202203

203204
## Figma URL Formats
204205

@@ -247,6 +248,30 @@ ralph-starter integrations fetch figma "ABC123" --figma-mode assets
247248
# Run the generated curl commands to download
248249
```
249250

251+
### Choose Your Model
252+
253+
Use `--model` to pick which AI model implements the design. Sonnet is fast and cost-effective for most UI work; Opus produces more nuanced implementations for complex layouts:
254+
255+
```bash
256+
# Fast iteration with Sonnet (recommended for most Figma workflows)
257+
ralph-starter run --from figma \
258+
--project "https://figma.com/file/ABC123/Dashboard" \
259+
--figma-mode components \
260+
--model claude-sonnet-4-5-20250929 \
261+
--max-iterations 5
262+
263+
# Maximum quality with Opus
264+
ralph-starter run --from figma \
265+
--project "https://figma.com/file/ABC123/Dashboard" \
266+
--figma-mode components \
267+
--model claude-opus-4-6 \
268+
--max-iterations 3
269+
```
270+
271+
:::tip Model Selection for Figma
272+
**Sonnet** is the sweet spot for Figma-to-code. It handles component structure, layout, and styling accurately at ~5x lower cost and faster iteration speed. Use **Opus** when you need complex state logic or intricate responsive behavior alongside the UI.
273+
:::
274+
250275
## Test Connection
251276

252277
Verify your authentication:
@@ -255,8 +280,72 @@ Verify your authentication:
255280
ralph-starter integrations test figma
256281
```
257282

283+
## Rate Limits & Caching
284+
285+
### Figma API Rate Limits
286+
287+
Figma enforces rate limits based on your **plan tier** and **seat type**. This matters because it determines how many API requests you can make per minute (or per month).
288+
289+
| Seat Type | Starter | Professional | Enterprise |
290+
|-----------|---------|-------------|------------|
291+
| Collab/Viewer (low) | 6/month | 5/min | 10/min |
292+
| Dev/Full (high) | 10/min | 15-50/min | 20-100/min |
293+
294+
:::warning Free & Starter Plans
295+
On the **Starter plan with a Collab/Viewer seat** (`limit-type=low`), you get only **6 requests per month**. Each `ralph-starter run --from figma` uses 2-4 API calls, so you can exhaust your budget in 1-2 runs. Upgrade to a **Professional plan with a Dev seat** ($12/month) for 10+ requests per minute.
296+
:::
297+
298+
### Community Files
299+
300+
When you access a **community file** (duplicated from the Figma Community), the **file owner's plan** determines your rate limits -- not your own plan. If the original author is on a free/starter plan, you'll be limited to 6 requests per month regardless of your plan.
301+
302+
**Fix:** Duplicate the file to your own workspace. This makes you the owner and applies your plan's limits.
303+
304+
### Response Caching
305+
306+
ralph-starter automatically caches Figma API responses in `~/.ralph/figma-cache/` with a 1-hour TTL. This means:
307+
308+
- **First run** fetches from the API and populates the cache
309+
- **Subsequent runs** (within 1 hour) use the cache with zero API calls
310+
- **Rate limited (429)?** Falls back to stale cache if available
311+
312+
This is especially useful for iterative development -- fetch once, then run the coding loop as many times as you want without touching the API.
313+
314+
To clear the cache and force a fresh fetch:
315+
316+
```bash
317+
rm -rf ~/.ralph/figma-cache/
318+
```
319+
320+
### Debugging API Issues
321+
322+
Use the `RALPH_DEBUG` environment variable to see every API request, response status, and rate limit headers:
323+
324+
```bash
325+
RALPH_DEBUG=1 ralph-starter run --from figma --project "your-figma-url"
326+
```
327+
328+
This shows:
329+
- Each API endpoint being called
330+
- HTTP status codes and retry-after values
331+
- Plan tier (`x-figma-plan-tier`) and limit type (`x-figma-rate-limit-type`)
332+
- Cache hits and stale cache fallbacks
333+
258334
## Troubleshooting
259335

336+
### "Figma API blocked for ~N day(s)"
337+
338+
This means CloudFront (Figma's CDN) has blocked your IP after too many rate-limited requests. The `retry-after` header shows days, not minutes.
339+
340+
**Solutions (pick one):**
341+
1. **Upgrade your Figma plan** to Professional with a Dev seat ($12/month) -- gives you 10+ req/min instead of 6/month
342+
2. **Use a VPN** to get a fresh IP, fetch once to populate the cache, then disconnect
343+
3. **Wait** for the block to expire (shown in the error message)
344+
345+
### "Figma API rate limit hit"
346+
347+
A transient rate limit (not a CDN block). ralph-starter will automatically retry once after respecting the `retry-after` header. If it fails again, wait 1-2 minutes and try again.
348+
260349
### "Invalid Figma token"
261350

262351
Your token may have expired or been revoked. Create a new token in Figma settings.
@@ -278,3 +367,4 @@ Assets are detected by name patterns. Rename your icon frames to include "icon",
278367
- **Variables API** requires Figma Enterprise plan (falls back to styles)
279368
- **Image export URLs** expire after 30 days
280369
- **Large files** may be slow; use `--figma-nodes` to target specific frames
370+
- **Starter plan (Collab seat)** limited to 6 API requests/month -- use caching or upgrade to Professional

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@
8181
"yaml": "^2.7.0",
8282
"zod": "^4.3.6"
8383
},
84+
"optionalDependencies": {
85+
"sharp": "^0.33.0"
86+
},
8487
"devDependencies": {
8588
"@biomejs/biome": "^2.3.13",
8689
"@commitlint/cli": "^20.3.1",

0 commit comments

Comments
 (0)