fmcp-screen-recipes
Skill10 starsChanged 29 days agoMITView on GitHub
Fast path cookbook — standart ekran tipleri (login/payment/profile/list/detail/form/onboarding/dashboard/settings) için 5 mega-adımlı recipe. Max 15 op/execute, cache-first discovery, her adımda Türkçe micro-report.
In this repository28 other files it gives its agents.
- ai-handoff-exportSkill
- apply-figma-design-systemSkill
- audit-figma-design-systemSkill
- code-design-mapperSkill
- component-documentationSkill
- design-drift-detectorSkill
- design-system-rulesSkill
- design-token-pipelineSkill
- ds-change-trackerSkill
- ds-impact-analysisSkill
- extract-contractSkill
- figjam-diagram-builderSkill
- figma-a11y-auditSkill
- figma-canvas-opsSkill
- figma-prototype-flowSkill
- figma-screen-analyzerSkill
- fix-figma-design-system-findingSkill
- fmcp-ds-audit-orchestratorSkill
- fmcp-intent-routerSkill
- fmcp-project-rulesSkill
- fmcp-screen-orchestratorSkill
- fmcp-token-sync-orchestratorSkill
- generate-figma-librarySkill
- generate-figma-screenSkill
- implement-designSkill
- inspiration-intakeSkill
- ux-copy-guidanceSkill
- visual-qa-compareSkill
The file
Files
FMCP Screen Recipes — Fast Path Cookbook
Kullanım (v3.1+):
fmcp-screen-orchestratorAdım 0.5 Fast Path 5/5 match olduğunda çağrılır. Bağımsız giriş noktası değil. Adım 1.6 (Text Style Resolution) canonical kopyası burada — orchestrator buraya referans verir, kod duplicate etmez.
Ne Zaman Kullanılır
Fast Path DEVREYE GİRER (hepsi TRUE olmalı):
- ✅ Tek ekran üretimi
- ✅ Standart ekran tipi: 9 recipe'ten biri match ediyor
- ✅ DS tanımlı:
active-ds.mdStatus: ✅ Aktif - ✅ Platform belli
- ✅ Custom animation / prototype YOK
Devreye GİRMEZ: Multi-screen flow, custom layout, animation, explicit generate-figma-screen talebi, DS GATE geçilmemişse.
5 Mega-Adımlı Akış
Max 15 op/execute. Her mega-adım sonrası tek satır Türkçe micro-report.
M1: Pre-Flight Discovery + Token + Text Style (1 execute, ~15 op)
M2: Frame + Structure + Modes (1 execute, ~12-14 op)
M3: Component Placement (toplu, 3-4/execute) (2-3 execute, ~12-15 op each)
↳ Her M3 execute sonrası: figma_scan_ds_compliance(threshold=85) inline gate
M4: Dark Variant (1 execute, ~4 op)
M5: Validate + Final Report (ZORUNLU: figma_scan_ds_compliance(detailed) + figma_validate_screen)Toplam execute: ~6-8 + 2-3 scan call. Hedef süre: ~10 dk. v1.9.4: Scan call'ları hızlıdır (~150ms), execute bütçesini yemezler.
3 MUTLAK KURAL
KURAL 1 — Fill Bind Zorunlu (frame + text dahil):
const paint = { type: 'SOLID', color: { r: 1, g: 1, b: 1 } };
const bound = figma.variables.setBoundVariableForPaint(paint, 'color', dsColorVar);
node.fills = [bound];Fill panel'de variable icon 🎨 GÖRÜNMELI. Hardcoded hex YASAK. Frame fill + text fill + primitive dahil TÜM node'lar.
KURAL 2 — Variant Seçim: DEFAULT Koru:
setPropertiesile SADECE recipe'de explicit belirtilen property'leri set et- Diğer TÜM property'leri DEFAULT bırak
Product→ main (default), Boolean kontroller → recipe'de explicit yoksa DEFAULT
KURAL 3 — Token Bind, Alias Resolve ETME:
setBoundVariable(property, importedVariable) ile bind et. Figma runtime alias chain'i otomatik çözer. valuesByMode okuma, alias traversal YASAK (timeout riski).
Mega-Adım Mapping
Aşağıdaki eski adımlar REFERANS amaçlıdır. AYRI AYRI execute ETME — mega-adım tablosunu takip et:
- M1: Adım 1 (validation) + 1.5 (discovery) + 1.6 (text style) → TEK execute
- M2: Adım 2 (frame) + 4b (mode) + 5.5 (content body) → TEK execute
- M3: Adım 6 (discovery) + 7 (placement) → 2-3 execute
- M4: Adım 8 (dark) → TEK execute
- M5: Adım 9 (validate) → 1-2 validate call
Adım 1 — Pre-Flight Check
Hiçbir figma_execute çağırma. Doğrula: active-ds.md ✅, screen_type geçerli, platform + device_preset geçerli, variants ≥1.
Micro-report: ✅ Pre-flight: screen_type=<X>, platform=<Y>, device=<Z>, variants=<V>
Adım 1.5 — Unified Pre-Flight Discovery
Cache-First (v3.0+): Önce .claude/design-systems/<active-ds>/tokens.md oku (<active-ds> = active-ds.md'den Library Name'in slug hali — ❖ Ana-DS → ana-ds, Material → material, vb.). Cache varsa ve <7 gün → token discovery ATLA, cache'ten kullan. Yoksa aşağıdaki execute'ları çalıştır, sonra cache'i güncelle.
Token name matching: DS nested path formatı (örn. "Spacing/spacing-100"). endsWith match kullan:
vars.find(v => v.name.endsWith("/" + suffix) || v.name === suffix)Execute 1 — Collection & Mode Discovery (7 op)
const colls = await figma.teamLibrary.getAvailableLibraryVariableCollectionsAsync();
function findColl(keywords) {
return colls.find(c => {
const n = c.name.toLowerCase().trim();
return keywords.some(kw => n.includes(kw));
});
}
const sizeColl = findColl(["semantic size", "semantic sizes", "size"]);
const colorsColl = findColl(["semantic color", "theme color"]);
const result = { availableColls: colls.map(c => ({name: c.name, key: c.key})), spacingTokenKeys: {}, collectionInfo: { colors: null, size: null }, surfaceKey: null };
if (sizeColl) {
const sizeVars = await figma.teamLibrary.getVariablesInLibraryCollectionAsync(sizeColl.key);
const suffixes = ["spacing-none","spacing-050","spacing-075","spacing-100","spacing-125","spacing-150","spacing-200"];
for (const s of suffixes) {
const f = sizeVars.find(v => v.name.endsWith("/"+s) || v.name === s);
if (f) result.spacingTokenKeys[s] = f.key;
}
if (sizeVars.length > 0) {
const first = await figma.variables.importVariableByKeyAsync(sizeVars[0].key);
const coll = await figma.variables.getVariableCollectionByIdAsync(first.variableCollectionId);
result.collectionInfo.size = { collId: coll.id, modes: coll.modes.map(m => ({name: m.name, modeId: m.modeId})) };
}
}
if (colorsColl) {
const colorsVars = await figma.teamLibrary.getVariablesInLibraryCollectionAsync(colorsColl.key);
const bgVar = colorsVars.find(v => v.name.toLowerCase().includes("background") && v.name.toLowerCase().includes("level-0"));
if (bgVar) result.surfaceKey = bgVar.key;
if (colorsVars.length > 0) {
const first = await figma.variables.importVariableByKeyAsync(colorsVars[0].key);
const coll = await figma.variables.getVariableCollectionByIdAsync(first.variableCollectionId);
result.collectionInfo.colors = { collId: coll.id, modes: coll.modes.map(m => ({name: m.name, modeId: m.modeId})) };
}
}
return result;Execute 2 — Critical Token Import (7 op)
const tokenKeyMap = {};
const spacingKeys = { /* Execute 1'den gelen spacingTokenKeys */ };
for (const [suffix, key] of Object.entries(spacingKeys)) {
try {
const imported = await figma.variables.importVariableByKeyAsync(key);
tokenKeyMap[suffix] = imported.id;
} catch(e) {}
}
return { tokenKeyMap };Micro-report: ✅ Pre-Flight Discovery: <N> collection, <M> token imported, surface=<found/missing>
Adım 1.6 — Text Style Resolution (v2.0+ — fontFamilies + seed fallback)
Dosyadaki mevcut text style'ları tara, role mapping + font family üret. importStyleByKeyAsync ÇAĞIRMA — direkt setTextStyleIdAsync(roleMap[role].id) kullan.
// Adım A: Sayfa boşsa ilk componentKey ile seed instance düşür (v2.0+ Page 4 senaryosu)
// Caller `seedComponentKey` değişkenini opsiyonel olarak tanımlar (componentKey cache'ten).
// Tanımsızsa sessizce skip edilir — styleMap boş dönebilir, fallback chain devreye girer.
let seedInst = null;
if (figma.currentPage.findAll(n => n.type === "TEXT").length === 0) {
const _seedKey = (typeof seedComponentKey !== "undefined") ? seedComponentKey : null;
if (_seedKey) {
try {
const seedComp = await figma.importComponentByKeyAsync(_seedKey);
seedInst = seedComp.createInstance();
figma.currentPage.appendChild(seedInst);
} catch(e) { /* fallback: keep going, styleMap may be empty */ }
}
}
// Adım B: findAll + getStyleByIdAsync
const allTexts = figma.currentPage.findAll(n => n.type === "TEXT");
const uniqueStyleIds = new Set();
for (const t of allTexts) { if (t.textStyleId && typeof t.textStyleId === 'string') uniqueStyleIds.add(t.textStyleId); }
const styleMap = {};
const fontFamilySet = new Set();
for (const id of uniqueStyleIds) {
try {
const style = await figma.getStyleByIdAsync(id);
if (style) {
styleMap[style.id] = { id: style.id, name: style.name, fontSize: style.fontSize || null, fontName: style.fontName || null };
if (style.fontName?.family) fontFamilySet.add(style.fontName.family); // v2.0+
}
} catch(e) {}
}
const roleKeywords = {
display: ["display","hero","amount","title-xl"], title: ["section-title","title","heading"],
subtitle: ["subtitle","body-semibold","body-bold"], body: ["body-medium","body-regular","body"],
caption: ["small","caption","footnote"], button: ["button"]
};
function findStyle(kws) { for (const kw of kws) { const m = Object.values(styleMap).find(s => (s.name||"").toLowerCase().includes(kw.toLowerCase())); if (m) return m; } return null; }
const roleMap = {};
for (const [role, kws] of Object.entries(roleKeywords)) { const m = findStyle(kws); if (m) roleMap[role] = { id: m.id, name: m.name, fontSize: m.fontSize }; }
if (!roleMap.display) {
const sorted = Object.values(styleMap).filter(s => s.fontSize).sort((a,b) => b.fontSize - a.fontSize);
if (sorted.length > 0) roleMap.display = { id: sorted[0].id, name: sorted[0].name, fontSize: sorted[0].fontSize };
}
// Adım C: Seed temizle (ekran dışına düşürürdü, kaldır)
if (seedInst) { try { seedInst.remove(); } catch(e) {} }
return {
totalStyles: Object.keys(styleMap).length,
styleMap,
roleMap,
fontFamilies: [...fontFamilySet], // v2.0+ — loadFontAsync için
};Micro-report: ✅ Text Style: <N> style, <M> role eşleşti, font: <family>
Kritik: fontFamilies[0] (DS'inizin gerçek font ailesi) sonraki tüm loadFontAsync({ family }) çağrılarında kullanılır. Hardcoded "Inter" YASAK — figma-canvas-ops Rule 8b-pre.
Adım 2 — Wrapper Frame + Background (Edge-to-Edge)
Ana frame: device preset boyutu, auto-layout VERTICAL, padding=0, gap=0, background DS variable'a bağlı.
Edge-to-Edge yapı:
Ana Frame (padding:0, gap:0, VERTICAL)
├── NavigationTopBar (FILL — edge-to-edge)
├── Content Body (FILL both, padding:spacing-100, gap:spacing-075)
│ └── Recipe component'leri
└── BottomNavBar (FILL — edge-to-edge, varsa)const frame = figma.createFrame();
frame.name = "<Screen Name> — <Device Preset>";
frame.resize(<width>, <height>);
frame.layoutMode = "VERTICAL";
frame.primaryAxisSizingMode = "FIXED";
frame.counterAxisSizingMode = "FIXED";
frame.paddingTop = 0; frame.paddingBottom = 0; frame.paddingLeft = 0; frame.paddingRight = 0;
frame.itemSpacing = 0;
if (surfaceKey) {
const bgVar = await figma.variables.importVariableByKeyAsync(surfaceKey);
const paint = { type: 'SOLID', color: { r: 1, g: 1, b: 1 } };
frame.fills = [figma.variables.setBoundVariableForPaint(paint, 'color', bgVar)];
}
return { frameId: frame.id };Micro-report: ✅ Frame: <device> (<w>×<h>), edge-to-edge, background bound
Adım 3 — ⏭️ DEVRE DIŞI
Breakpoint bind frame boyutunu bozuyor (375 vs 402). Device preset boyutu korunur.
Adım 4 — Theme + Size Mode Setup
Collection/mode bilgisi Adım 1.5'ten gelir (ayrı execute yok).
Adım 4b — Mode apply:
const frame = await figma.getNodeByIdAsync(frameId);
if (collectionInfo.colors) {
const coll = await figma.variables.getVariableCollectionByIdAsync(collectionInfo.colors.collId);
const lightMode = collectionInfo.colors.modes.find(m => m.name.toLowerCase().includes("light"));
if (lightMode) frame.setExplicitVariableModeForCollection(coll, lightMode.modeId);
}
if (collectionInfo.size) {
const coll = await figma.variables.getVariableCollectionByIdAsync(collectionInfo.size.collId);
const kws = { mobile:["mobil","mobile"], tablet:["tablet"], desktop:["web","desktop"], web:["web","desktop"] };
const sizeMode = collectionInfo.size.modes.find(m => (kws[platform]||["mobil"]).some(k => m.name.toLowerCase().includes(k)));
if (sizeMode) frame.setExplicitVariableModeForCollection(coll, sizeMode.modeId);
}
return { modesApplied: true };Micro-report: ✅ Theme: Light, Size: <modeName>
Adım 5.5 — Content Body Wrapper
const parentFrame = await figma.getNodeByIdAsync(frameId);
const contentBody = figma.createFrame();
contentBody.name = "Content Body";
contentBody.layoutMode = "VERTICAL";
parentFrame.appendChild(contentBody); // ÖNCE (Rule 11)
contentBody.layoutSizingHorizontal = "FILL"; // SONRA
contentBody.layoutSizingVertical = "FILL";
const paddingVar = await figma.variables.importVariableByKeyAsync(spacing100Key);
const gapVar = await figma.variables.importVariableByKeyAsync(spacing075Key);
contentBody.setBoundVariable("paddingLeft", paddingVar);
contentBody.setBoundVariable("paddingRight", paddingVar);
contentBody.setBoundVariable("paddingTop", paddingVar);
contentBody.setBoundVariable("paddingBottom", paddingVar);
contentBody.setBoundVariable("itemSpacing", gapVar);
contentBody.fills = [];
return { contentBodyId: contentBody.id };Micro-report: ✅ Content Body: FILL both, padding=spacing-100, gap=spacing-075
Adım 6 — Component Discovery
Cache-First (v3.0+): Önce .claude/design-systems/<active-ds>/components.md oku (DS adı active-ds.md'den). Cache varsa → figma_search_assets ATLA, direkt importComponentByKeyAsync kullan. Yoksa: figma_search_assets(query="<keywords>") + Rule 24 fallback.
Micro-report: ✅ Component keşfi: <N> bulundu, <M> eksik
Adım 7 — Recipe Component Placement
3-4 component TEK execute'ta. Parent routing: edge-to-edge (NavigationTopBar, BottomNavBar) → Ana Frame, diğer her şey → Content Body.
const edgeNames = /^(navigation|nav|top|bottom|status|tabbar|tab_bar)/i;
const parentId = edgeNames.test(spec.name) ? frameId : contentBodyId;Text Style Binding: await textNode.setTextStyleIdAsync(roleMap[role].id) — DİREKT bağla, importStyleByKeyAsync ÇAĞIRMA, fontSize set ETME.
Text rolü mapping: display→Amount/Hero, title→Section Header, subtitle→Card Title, body→Body text, caption→Small/Info.
Adım 8 — Dark Variant
const lightFrame = await figma.getNodeByIdAsync(lightFrameId);
const darkFrame = lightFrame.clone();
figma.currentPage.appendChild(darkFrame);
darkFrame.x = lightFrame.x + lightFrame.width + 80;
darkFrame.name = lightFrame.name + " — Dark";
const coll = await figma.variables.getVariableCollectionByIdAsync(semColorsCollId);
darkFrame.setExplicitVariableModeForCollection(coll, darkModeId);
return { darkFrameId: darkFrame.id };Adım 9 — Validation + Final Report (v1.9.4 Güçlendirildi)
ZORUNLU gate — atlama YASAK. Her ekran için iki aşamalı doğrulama:
9a. Inline scan (M3/M4 sonrası, isteğe bağlı retry):
figma_scan_ds_compliance(nodeId=frameId, threshold=85)passed: falseveyacoverage.paddings.pct < 90veyacoverage.radius.pct < 90veyacoverage.textStyle.pct < 90→ M3/M4 retry zorunlu.samples.hardcodedHexdöndüyse → o node'lardaki fill'ler içinsetBoundVariableForPaintçağrısı eksik, derhal düzelt.samples.hardcodedFontSizedöndüyse → o text'ler içinsetTextStyleIdAsync(roleMap[role].id)çağrısı eksik.samples.primitiveFramesdöndüyse → o frame'ler için Ana-DS'de component var mı ara (figma_search_assets); varsa instance'a dönüştür.overflow.overflowPx > 0veclipsContent: true→ içerik kesiliyor, kullanıcıya "scroll mu, body genişletme mi?" sor.
9b. Final validate (her frame için, ZORUNLU):
figma_validate_screen(frameId, minScore=80)- Skor <80 → 3 retry; 3× fail → kullanıcıya
generate-figma-screenskill'ine fallback öner.
Son Rapor (ZORUNLU alanlar):
- Screen type, DS, device, variants
- Frame ID'leri (light/dark)
- Score: validate + scan skorları birlikte (örn. "validate: 87, scan: 89")
- Coverage yüzdeleri: fills/paddings/radius/itemSpacing/textStyle/textColor (scan response'tan)
- Kullanılan library instance listesi + primitive fallback listesi (varsa)
- Token binding sayıları
- Overflow durumu (body kesiliyor mu?)
- Toplam execute sayısı, süre
- Hardcoded hex/fontSize sample'ları (varsa — kullanıcıya gösterilir, "bilinçli skip" değil "acil düzeltilecek")
Device Presets Lookup Table
Mobile
| Device | W | H | Keywords |
| iPhone 17 | 402 | 874 | mobile, iphone, ios |
| iPhone 16 & 17 Pro | 402 | 874 | iphone pro |
| iPhone 16 | 393 | 852 | iphone 16 |
| iPhone 16 Pro Max | 440 | 956 | pro max |
| iPhone 16 Plus | 430 | 932 | iphone plus |
| iPhone Air | 420 | 912 | iphone air |
| iPhone 13 & 14 | 390 | 844 | iphone 13, iphone 14 |
| Android Compact | 412 | 917 | android |
| Android Medium | 700 | 840 | android tablet |
Default: mobile → iPhone 17, android → Android Compact.
Tablet
| Device | W | H |
| iPad Pro 11" | 834 | 1194 |
| iPad Pro 12.9" | 1024 | 1366 |
Default: tablet → iPad Pro 11".
Desktop / Web
| Device | W | H |
| Desktop | 1440 | 900 |
| Desktop HD | 1920 | 1080 |
| MacBook Pro 14" | 1512 | 982 |
| MacBook Pro 16" | 1728 | 1117 |
Default: desktop/web → Desktop 1440×900.
9 Screen Type Recipes
Her recipe = component listesi + yerleşim sırası + search keyword'leri + setProperties.
Recipe 1: Login
Trigger: login, giriş, oturum aç, sign in
- AppBar —
["navigation top", "appbar"]setProperties:{ "Subtitle": false, "Right Controls": false } - Logo —
["logo", "brand"] - Welcome Text (H1) —
["heading", "display"] - Subtitle Text —
["body medium", "text body"] - Email Input —
["text field", "input", "email"] - Password Input —
["password", "text field password"] - Primary Button ("Giriş Yap") —
["button primary"]setProperties:{ "Value": "Giriş Yap" } - Forgot Password Link —
["link", "text button"] - Divider —
["divider"] - Register Link —
["text button", "link"]
Recipe 2: Payment
Trigger: ödeme, payment, checkout, satın al
- NavigationTopBar —
["navigation top", "appbar"]setProperties:{ "Title Text": "Ödeme", "Right Controls": false, "Subtitle": false, "Product": "main" } - Amount Display —
["display large", "hero text"] - Currency Label —
["body small", "caption"] - Section Header —
["section header", "subtitle"] - Payment Method Cards (×3) —
["card payment", "list item"] - Add New Method Button —
["button secondary"] - Divider —
["divider"] - CTA Button —
["button primary large"]setProperties:{ "Value": "Ödemeyi Tamamla" } - Security Info —
["text small", "caption"]
🔀 Content Override (reference_benchmark varsa — v1.9.9+ G20):
reference_benchmark input dolu ise (görsel upload veya Figma node URL):
inspiration-intakeskill'i çağır.structural_intentJSON üret:{ "sections": [ {"role": "amount", "text_hints": ["2.124,90 TL"]}, {"role": "segmented_tabs", "text_hints": ["Tek Çekim", "3 Taksit"]}, {"role": "method_card", "count": 2, "text_hints": [...]} ] }- Recipe 2 bileşen listesine override uygula (sadece text + count):
- Amount Display text →
sections[amount].text_hints[0] - Payment Method Cards
count→sections[method_card].count(varsayılan 3, referansta 2 olabilir) - Method Card text slot →
text_hintsmap (örn. "Tek Çekim" / "3 Taksit") - Security Info → referansta varsa extract, yoksa default
- Amount Display text →
⚠️ Override sadece TEXT + COUNT. Color/spacing/radius/font hep DS tokens'a bound kalır (K5 Token-Only Enforcement). Referansın hex değerleri, px piksel ölçüleri KULLANILMAZ.
Recipe 3: Profile
Trigger: profil, profile, hesap, account
- AppBar —
["navigation top"]setProperties:{ "Title Text": "Profilim" } - Avatar —
["avatar large", "profile picture"] - User Name Text —
["heading", "display medium"] - User Email Text —
["body", "text secondary"] - Divider —
["divider"] - Menu List Items (×4) —
["list item", "menu row"] - Destructive Button ("Çıkış Yap") —
["button destructive"]setProperties:{ "Value": "Çıkış Yap" }
Recipe 4: List
Trigger: liste, list, arama, search, katalog
- AppBar —
["navigation top"]setProperties:{ "Title Text": "Arama" } - Search Bar —
["search", "search bar"] - Filter Chips Row —
["chip", "filter chip"] - Card List Items (×N) —
["card", "list card"] - Pagination —
["pagination"] - FAB (opsiyonel) —
["fab", "floating button"]
Recipe 5: Detail
Trigger: detay, detail, ürün detay, product
- AppBar —
["navigation top"]setProperties:{ "Right Controls": true } - Hero Image —
["image large", "hero"] - Title Text —
["heading large", "display"] - Price + Rating Row —
["price", "rating"] - Description Text —
["body", "text body"] - Stats Section —
["stat", "info row"] - CTA Button —
["button primary"]setProperties:{ "Value": "Sepete Ekle" }
Recipe 6: Form
Trigger: form, başvuru, kayıt, application
- AppBar —
["navigation top"]setProperties:{ "Title Text": "Başvuru" } - Progress Indicator —
["stepper", "progress"] - Field Group 1 (3-4 input) —
["text field", "input"] - Field Group 2 —
["select", "dropdown", "date picker"] - Checkbox / Terms —
["checkbox", "agreement"] - Submit Button —
["button primary"]setProperties:{ "Value": "Gönder" }
Recipe 7: Onboarding
Trigger: onboarding, tanıtım, karşılama, welcome
- Hero Image —
["illustration", "image hero"] - Title Text —
["display", "heading large"] - Subtitle Text —
["body", "text secondary"] - Pagination Dots —
["dots", "page indicator"] - Primary Button —
["button primary"]setProperties:{ "Value": "Başla" } - Skip Link —
["text button", "link"]
Recipe 8: Dashboard
Trigger: dashboard, özet, summary, panel
- AppBar —
["navigation top"]setProperties:{ "Title Text": "Özet" } - Stats Cards (×4) —
["stat card", "metric card"] - Chart —
["chart", "graph"] - Section Header —
["section header"] - Activity List Items (×N) —
["list item", "activity row"]
Recipe 9: Settings
Trigger: ayarlar, settings, tercihler
- AppBar —
["navigation top"]setProperties:{ "Title Text": "Ayarlar" } - Section Headers —
["section header"] - Toggle Rows —
["list item toggle", "setting row"] - Info Row —
["list item", "nav row"] - Destructive Button —
["button destructive"]setProperties:{ "Value": "Hesabı Sil" }
Primitive Fallback Pattern
Component bulunamazsa token-bound primitive ile inşa et. Tüm visual properties variable'a bağlı olmalı:
const card = figma.createFrame();
card.name = "... (primitive fallback)";
card.layoutMode = "HORIZONTAL";
card.setBoundVariable("cornerRadius", radiusSmVar);
card.setBoundVariable("paddingLeft", spacingMdVar);
// ... diğer padding/gap bind'ları
const paint = { type: 'SOLID', color: { r: 1, g: 1, b: 1 } };
card.fills = [figma.variables.setBoundVariableForPaint(paint, 'color', surfaceVar)];
parent.appendChild(card); // ÖNCE
card.layoutSizingHorizontal = "FILL"; // SONRA (Rule 11)Chunking Kuralları
- Max 15 atomic op / figma_execute
- 3-4 component TEK execute'ta yerleştir
- Timeout:
15000ms yeterli (15 op ≈ 200-300ms) - Her component için AYRI execute YASAK
Error Recovery
| Hata | Aksiyon |
| DS GATE yok | Fast Path iptal, orchestrator'a dön |
| Device bulunamadı | Default kullan (iPhone 17 / Desktop 1440) |
| Colors collection yok | Light-only, dark skip |
| Component 0 sonuç | Primitive fallback |
| Execute timeout | Op sayısını azalt, böl |
| Style import fail | Rule 23 try-catch, roleMap fallback |
| 3× validate fail | Kullanıcıya generate-figma-screen öner |
Rule 24 — Component Fallback Chain (v1.9.9+ / v3.1+)
figma_search_assets library components boş dönerse (variables var ama component instance yok) sırayla şu yolu takip et:
24.0 — Live Enumerate (v3.3+ — İLK SIRA):
- DS Library Registry'de
libraryFileKeykayıtlıysa:figma_enumerate_published_components(libraryFileKey, filter?)→ componentKey listesi (REST; dosya açıksafigma_enumerate_library_componentstercih et)figma_get_library_variables(query?)→ variableKey listesi (teamLibrary — hedef dosyada çalışır)
- Başarılıysa 24.1-24.4 atlanır → direkt
importComponentByKeyAsync(key)/importComponentSetByKeyAsync(key). - Registry boş veya REST token yoksa 24.1'e düş.
24.1 — REST API enumerate:
- Response'ta
_restFallbackHintvarsa oku. FIGMA_REST_TOKENenv var set ise:figma_rest_api(endpoint="/v1/files/<LIBRARY_FILE_KEY>/components")çağır.- Dönen
componentKey'leriimportComponentByKeyAsyncile kullan.
24.2 — Cache-populated keys (user-local):
~/.claude/data/fcm-ds/<file-key>/components.mdoku.- Yaygın rol →
componentKeymapping varsa direktimportComponentByKeyAsync. - Cache yok/stale ise Step 3.1 Cache Populate (bkz.
generate-figma-screen) otomatik tetikler.
24.3 — Token-bound primitive fallback (Rule 3 — MEŞRU):
- Yukarıdakiler fail ise:
createFrame+ her fill/padding/radius/textStyle içinsetBoundVariable/setBoundVariableForPaint/setTextStyleIdAsync. - Sayma kuralı:
totalBindings >= createFrameCount→code-warnings.tsADVISORY döner (BLOCKING değil). - Hardcoded renk/spacing/font YASAK — sadece bound primitives.
24.4 — Full stop:
- 24.1-24.3 hepsi fail ise kullanıcıya: "Library subscribe yok + REST token yok + cache boş. Manuel component sürüklemen gerek."
⚠️ figma_search_assets boş yanıt ≠ fallback yasağı. Fallback chain Rule 3 (fmcp-screen-orchestrator) ile uyumlu ve server-level enforcement tarafından ADVISORY olarak kabul edilir.
Known Limitations
- Ana-DS dışında test edilmedi — başka DS için isim farkı olabilir
- Dark mode validate ayrı ölçülmez — manuel göz kontrolü gerekli
- 9 recipe sabit — yeni tip → generate-figma-screen
- Multi-screen ve prototype/interactions YOK
- Component search false match riski — setProperties ile doğrula
Skill References
skills/fmcp-screen-orchestrator/SKILL.md— Fast Path tetiklenmeskills/figma-canvas-ops/SKILL.md— Rule 5a CHUNKING + Rule 22 Async + Rule 23 Style zorunlu.claude/design-systems/active-ds.md— DS GATE state.claude/design-systems/<active-ds>/tokens.md— Token cache (DS adıactive-ds.md'den dinamik).claude/design-systems/<active-ds>/components.md— Component cache
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

