Mert Özen Her Satırda Daha İleri
Frontend UI/UX Tasarım İlkeleri — #11

Figma'dan Koda: Dev Mode, Auto Layout'tan Flexbox'a, Variables'tan Token'a ve Figma MCP ile AI Destekli Handoff

Mert Özen 14 Kas 2026 13 dk 16 görüntülenme
Figma'dan Koda: Dev Mode, Auto Layout'tan Flexbox'a, Variables'tan Token'a ve Figma MCP ile AI Destekli Handoff

Figma'dan koda geçişte sayıları değil niyeti taşımak gerekir: Auto Layout'un FILL ve HUG ayarları Flexbox'a, Variables DTCG token'larına, tasarım component'leri Code Connect ile kod component'lerine bağlanır. Bookstore'un sepet barını Auto Layout JSON'undan CSS'e çeviriyor, kopyalanmış piksellerin 768 pikselde ve dark mode'da bozulduğunu ölçüyor, Figma variable'larıyla token'lar arasındaki farkı yakalıyor ve Figma MCP server'ın plan koşullarını resmî dokümantasyondan anlatıyoruz.

Sürüm notu: Bu yazıdaki script'ler Node.js 24 ile çalıştırılmış, örnek ekranlar Playwright 1.65 ile Chromium 158'de render edilip ölçülmüştür; token'lar bir önceki yazıdaki DTCG (Design Tokens Community Group; W3C'nin, yani web standartlarını yayımlayan kuruluşun token formatını belirleyen topluluk grubu) 2025.10 dosyalarıdır. Figma, Dev Mode, Code Connect ve Figma MCP (Model Context Protocol; AI asistanlarının dış araçlara bağlandığı protokol) server bu yazıda çalıştırılmadı; bunlarla ilgili anlatılanlar Kasım 2026 itibarıyla Figma'nın resmî dokümantasyonuna dayanıyor ve Figma'dan gelen JSON örnekleri dokümante edilen alan adlarıyla elle yazıldı.

Önce Tahmin Et

Sitedeki serilerin ortak örnek uygulaması Bookstore (bir online kitapçı) için tasarımcı, 09. yazıdaki mobil sepet barını Figma'da 390 piksellik bir telefon frame'i içinde çizmiş ve "Ready for dev" olarak işaretlemiş. bookstore-web'de bu barı yazan geliştirici Dev Mode'u açıp gördüğü ölçüleri ve renkleri olduğu gibi CSS'e geçirmiş:

/* 390 px'lik tasarım frame'inde görünen ölçü ve renkler, olduğu gibi kopyalandı */
.cart-bar { position: fixed; bottom: 0; left: 0; width: 390px; height: 72px; padding: 12px 16px; display: flex; justify-content: space-between; align-items: center; background: #FFFFFF; }
.count { font-size: 14px; color: #6B6F75; }
.total { font-size: 16px; font-weight: 700; color: #202224; }
.checkout { width: 138px; height: 48px; display: flex; align-items: center; justify-content: center; border-radius: 6px; background: #3366D6; color: #FFFFFF; font-weight: 600; }

390 piksellik telefonda ekran tasarımın birebir aynısı. 768 piksellik bir tablette bar ne kadar geniş olur ve Checkout nerede durur? Kullanıcı dark mode'daysa bar ne renk olur? #3366D6 bir önceki yazıda token'lara taşıdığımız --color-action ile aynı renk mi? Tasarımcı mavinin tonunu değiştirdiğinde bu satırı kim, nasıl fark eder?

Bu son yazıda token'ların diğer ucuna, tasarım aracına bakıyoruz. Amaç Figma'yı öğretmek değil; tasarım dosyasını geliştirici gözüyle okumak ve oradan koda geçerken nelerin kaybolduğunu ölçmek.

Önce ölçelim

Script üç iş yapıyor. Barın Figma'daki Auto Layout ayarlarını, Figma Plugin API'sinin property adlarıyla yazılmış bir JSON'dan CSS'e çeviriyor ve variable'a bağlanmamış değerleri listeliyor. Aynı barı Auto Layout'tan üretilmiş hâliyle ve kopyalanmış piksellerle 390 ve 768 piksel genişlikte ve dark mode'da render ediyor. Son olarak Figma'nın REST (HTTP üzerinden kaynak odaklı çalışan API tarzı) API'sinin variables yanıtı biçimindeki bir dosyayı bir önceki yazının DTCG token'larıyla karşılaştırıyor:

npm run tokens
node scripts/11-handoff.mjs
--- Auto Layout -> CSS
CartBar: display: flex; flex-direction: row; justify-content: space-between; align-items: center; gap: var(--space-4); padding: var(--space-3) var(--space-4) var(--space-3) var(--space-4); flex: 1 1 0; background: var(--color-surface-raised);
Summary: display: flex; flex-direction: column; justify-content: flex-start; align-items: flex-start; gap: 0px; flex: none;
Count: color: var(--color-text-muted); font-size: 14px; font-weight: 400;
Total: color: var(--color-text); font-size: 16px; font-weight: 700;
Checkout: display: flex; flex-direction: row; justify-content: center; align-items: center; padding: 0px var(--space-8) 0px var(--space-8); flex: none; height: 48px; border-radius: 6px; background: var(--color-action);
Label: color: var(--color-on-action); font-size: 16px; font-weight: 600;
values not bound to a variable: Checkout.height = 48, Checkout.cornerRadius = 6
--- rendered
  auto layout at 390 px: bar 390 px wide, checkout 138x48, 16 px from the right edge
  auto layout at 768 px: bar 768 px wide, checkout 138x48, 16 px from the right edge
  auto layout at 390 px: dark: bar background oklch(0.4 0.008 264)
  copied values at 390 px: bar 390 px wide, checkout 138x48, 16 px from the right edge
  copied values at 768 px: bar 390 px wide, checkout 138x48, 394 px from the right edge
  copied values at 390 px: dark: bar background rgb(255, 255, 255)
--- variables vs tokens
colour variables: 20, in both: 18, only in Figma: white, color/brand-accent
different values: blue/600 (light) Figma #3366d6, code #3766d5; color/action (light) Figma #3366d6, code #3766d5
semantic colours only in code: 10 (color/border, color/border-strong, color/link, color/success-text, ...)

390 pikselde iki bar da aynı. 768 pikselde kopyalanmış bar 390 pikselde kalıyor ve Checkout sağ kenardan 394 piksel uzakta; dark mode'da bar beyaz kalıyor. Auto Layout'tan üretilen bar ise her genişlikte ekranı dolduruyor ve dark'ta 09. yazıdaki yükseltilmiş yüzey tonunu alıyor. Variable karşılaştırması da kopyalanan #3366D6'nın kaynağını gösteriyor: Figma dosyasındaki blue/600 koddaki token'dan bir ton farklı.

Figma'yı Geliştirici Gözüyle Okumak

Bir Figma dosyasında geliştiricinin bilmesi gereken birkaç kavram var. Frame, içine başka katmanlar konan kutu; bir ekran da, bir buton da frame olabilir. Component, tekrar kullanılan bir tasarım parçasının ana tanımı; instance o component'in bir kullanımı ve ana tanım değişince instance'lar da değişiyor. Variant'lar bir component'in farklı hâlleri: "Button, Primary, Disabled" gibi. Bunlar kodda sırasıyla bir component, onun bir kullanımı ve input'ları ya da state'leri. Auto Layout'suz frame'lerde çocukların ebeveyn büyüdüğünde nasıl davranacağını constraint'ler belirliyor (sola, sağa, ortaya sabitlenmek ya da ölçeklenmek); bu, CSS'te absolute konumlandırmaya daha yakın.

Dev Mode, Figma'nın geliştiriciye yönelik çalışma alanı. Figma yardım sayfasına göre burada seçilen katmanın property'leri ve otomatik üretilen kod parçası görülebiliyor, uygulanan variable'lar ve stiller, tasarımcının notları ve ölçüleri, "ready for dev" olarak işaretlenmiş bölümler ve bir frame'in geçmişindeki değişikliklerin karşılaştırması inceleniyor. Dev Mode Professional, Education, Organization, Government ve Enterprise planlarında var; bildirimler için Full ya da Dev seat gerekiyor.

Dev Mode'un gösterdiği kod bir başlangıç noktası, kopyalanacak sonuç değil. Kopyalanmış CSS'in iki hatası, ölçümün "copied values" satırlarında görülüyor: tasarım 390 piksellik bir frame'de çizildiği için oradaki genişlikler sabit sayılar olarak geliyor ve renkler variable yerine hex değer olarak alınınca tema bilgisi kayboluyor. Okunması gereken, sayının kendisi değil arkasındaki niyet: "bu bar ekranı doldurur", "bu buton içeriği kadar geniş", "bu renk birincil işlem rengi".

Auto Layout ≈ Flexbox

Auto Layout, bir frame'in çocuklarını tek bir eksende sıralayan ve aralarındaki boşluğu, padding'i ve hizalamayı yöneten özellik. Bu tarif CSS'teki Flexbox'ın neredeyse aynısı; Figma Plugin API'sindeki property adlarıyla eşleme şöyle:

Figma (Plugin API)CSS
layoutMode: HORIZONTAL / VERTICALdisplay: flex, flex-direction: row / column
itemSpacinggap
paddingTop/Right/Bottom/Leftpadding
primaryAxisAlignItems: MIN / CENTER / MAX / SPACE_BETWEENjustify-content
counterAxisAlignItems: MIN / CENTER / MAX / BASELINEalign-items
layoutWrap: WRAPflex-wrap: wrap
layoutSizingHorizontal: FILL (ana eksende)flex: 1 1 0
layoutSizingHorizontal: HUGflex: none, genişlik içerikten
layoutSizingHorizontal: FIXEDwidth ve flex-shrink: 0

Figma'nın arayüzünde bu üç sizing seçeneği "Hug contents", "Fill container" ve "Fixed" olarak geçiyor. Plugin API dokümantasyonuna göre HUG yalnız Auto Layout frame'lerinde ve metin katmanlarında, FILL yalnız bir Auto Layout frame'inin çocuklarında geçerli. Bizim çevirici bu kuralları uyguluyor; FILL'in anlamı ebeveynin yönüne bağlı:

// sizing: FILL ebeveynin ana ekseninde büyür ya da çapraz eksende gerilir, HUG içeriğin boyunu alır
const row = parent?.layoutMode === 'HORIZONTAL';
for (const [axis, size] of [['Horizontal', 'width'], ['Vertical', 'height']]) {
  const mode = node[`layoutSizing${axis}`];
  const main = parent && (row ? axis === 'Horizontal' : axis === 'Vertical');
  if (mode === 'FILL') {
    if (main) css.flex = '1 1 0';
    else if (parent) css['align-self'] = 'stretch';
    else css[size] = '100%';
  } else if (mode === 'FIXED') {
    css[size] = value(node, size, node[size], variables, unbound);
    if (main) css['flex-shrink'] = '0';
  } else if (mode === 'HUG' && main) {
    css.flex = 'none';
  }
}

Ölçümün ilk bölümü bu çeviricinin çıktısı. Barın kendisi FILL, yani ekran kadar geniş; özet ve buton HUG, yani içerikleri kadar; arada space-between. Kopyalanmış CSS'teki width: 390px ve width: 138px bu niyeti iki sabit sayıya indirgiyor; 138 tesadüfen doğru (buton içeriği kadar geniş), 390 ise yalnız tek bir ekranda doğru. Flexbox'ın kendisi CSS3 serisinin Flexbox yazılarında; Figma'nın daha yeni olan grid Auto Layout'unun karşılığı CSS Grid.

Variables'tan Token'a

Figma Variables, tasarım dosyasındaki adlandırılmış değerler: renk, sayı, metin ve boolean. Collection'lar variable'ları grupluyor, mode'lar bir collection'ın farklı bağlamlardaki değerlerini tutuyor. Bir önceki yazının diliyle: primitive bir collection tek mode'lu bir palet, semantic bir collection "Light" ve "Dark" mode'ları olan bir set; Figma'daki mode, DTCG resolver'ındaki modifier context'inin karşılığı. Variable adlarındaki eğik çizgi (color/action) gruplamayı veriyor; DTCG'de bu color.action, CSS'te --color-action.

Ölçümdeki CSS'in tek bir hex değer içermemesi bu bağlantıdan geliyor: barın padding'i ve gap'i space/3 ve space/4 variable'larına, rengi color/surface-raised'e bağlı ve çevirici her bağlı değeri ilgili token'ın CSS değişkenine çeviriyor. Bağlı olmayan iki değer, butonun 48 piksel yüksekliği ve 6 piksel köşe yarıçapı, ayrıca listeleniyor. Token'larımızda button.min-height ve button.radius zaten var; tasarım dosyasında da variable'a bağlanmaları gereken değerler bunlar. Figma'nın yardım sayfasına göre her variable'a Web, iOS ve Android için bir code syntax da yazılabiliyor; var(--color-action) yazılırsa Dev Mode'un kod parçası hex yerine token'ı gösteriyor.

Variable'ları dosyadan dışarı almanın resmî yolu Figma REST API'sinin variables endpoint'leri; dokümantasyona göre bu endpoint'ler yalnız Enterprise planında ve okuma için file_variables:read scope'uyla kullanılabiliyor. Bir önceki yazıda kullandığımız Terrazzo'nun tz import komutu da Figma dosyasından bir DTCG resolver dosyası üretebiliyor, ama Terrazzo'nun dokümantasyonuna göre variable'lar için yine Enterprise planı gerekiyor; stiller daha düşük planlarda da içe aktarılabiliyor. Figma'nın resmî yardım sayfalarında variable'ları doğrudan DTCG olarak dışa aktaran yerleşik bir özellik bulamadık; topluluk eklentileri bu boşluğu dolduruyor ve hangisinin 2025.10'a ne kadar uyduğu ayrıca doğrulanmalı.

Hangi yolla alınırsa alınsın asıl soru aynı: tasarım ve kod aynı değerleri mi kullanıyor? Script Figma'nın yanıt biçimindeki dosyayı token'larla karşılaştırıyor ve üç tür fark buluyor. Aynı adla iki tarafta da olan 18 renkten biri farklı: tasarımcı blue/600'ü #3366d6'ya çekmiş, kodda #3766d5; bu fark alias üzerinden color/action'ın açık tema değerine de geçiyor. color/brand-accent yalnız Figma'da; ya koda eklenmeli ya da tasarımdan çıkarılmalı. color/border ve color/link gibi 10 semantic renk yalnız kodda; bu dosyada tanımlanmamış olmaları, tasarımcının o ekranlarda serbest renk kullandığı anlamına gelebilir. Bu karşılaştırma CI'da düzenli çalışırsa, Önce Tahmin Et'teki "tasarımcı tonu değiştirince kim fark eder?" sorusunun cevabı bir build uyarısı oluyor.

Code Connect: Tasarım Component'ini Kod Component'ine Eşlemek

Token'lar değerleri bağlıyor; Code Connect component'leri bağlıyor. Figma'nın tanımına göre Code Connect, koddaki component'leri Figma'daki karşılıklarına eşliyor; böylece Dev Mode, seçilen bir buton instance'ı için otomatik üretilmiş genel bir kod yerine projenin kendi component'inin kullanımını gösteriyor, Figma MCP server da aynı eşlemeyi kullanıyor. İki yolu var: Figma'nın içinden, GitHub'a ya da dosya yollarına bağlanarak kurulan UI ve terminalden çalışan, şablon dosyalarıyla property eşlemesi yapılabilen CLI. GitHub'daki figma/code-connect README'si React, Storybook, SwiftUI ve Jetpack Compose yanında Angular ve Web Components'i kapsayan bir HTML entegrasyonunu sayıyor. Code Connect Professional ve üstü planlarda, Full ya da Dev seat ile kullanılabiliyor.

Bookstore için anlamı şu: tasarımdaki "Button / Primary / Disabled" instance'ı seçildiğinde Dev Mode, 07. yazıdaki state setine uygun Angular component'ini ve aria-disabled kullanımını göstermeli; hex kodlu bir div değil. Bu eşleme yoksa her geliştirici aynı butonu yeniden yazıyor ve 07'de ölçtüğümüz focus ve disabled hataları her seferinde yeniden doğuyor.

Figma MCP Server ile AI Destekli Handoff

MCP üzerinden çalışan Figma MCP server, bir AI kodlama asistanına seçilen tasarımın yapısını, variable'larını ve ekran görüntüsünü veriyor. Figma'nın geliştirici dokümantasyonunda iki seçenek var: önerilen remote server, Figma'nın https://mcp.figma.com/mcp adresindeki barındırılan endpoint'ine masaüstü uygulaması olmadan bağlanıyor ve en geniş özellik setini sunuyor; desktop server ise Figma masaüstü uygulaması üzerinden yerelde çalışıyor ve dokümantasyona göre belirli kurumsal ihtiyaçlar için düşünülmüş, Dev ya da Full seat gerektiriyor. Tasarım dosyasına yazma gibi yeni özellikler yalnız remote server'da.

Plan ve seat koşulları yazım anında doğrulanmalı, çünkü kaynaklar arasında bile fark var. Kasım 2026'da geliştirici dokümantasyonundaki tabloya göre Starter planında ya da ücretli planlarda View ve Collab seat'lerinde ayda en fazla 20 araç çağrısı yapılabiliyor; Full ve Dev seat'lerde sınır Professional planında günde 200 ve dakikada 10, Enterprise'da günde 600 ve dakikada 20. Aynı tarihte GitHub'daki figma/mcp-server-guide README'si ise Starter ve View/Collab için ayda 6 çağrı yazıyor. Sınırlar tasarım dosyasından okuyan araçlar için geçerli; dosyaya yazan bazı araçlar muaf.

Neyi iyi yapıyor? Guide'a göre get_design_context seçimin yapılandırılmış bir temsilini, varsayılan olarak React ve Tailwind biçiminde veriyor; get_variable_defs seçimde kullanılan variable'ları ve stilleri çıkarıyor, get_screenshot görsel referans sağlıyor. Asistan bu bağlamla Auto Layout'u, boşlukları ve hiyerarşiyi ekran görüntüsünden tahmin etmek zorunda kalmıyor. Nerede kendi kütüphanene uymayan kod üretir? Guide'ın kendi ifadesiyle, Code Connect yoksa model component'leri tahmin ediyor. Angular ve kendi token'larınla çalışan bir projede varsayılan React ve Tailwind çıktısı yalnız bir başlangıç; asistan butonu senin bookstore-button component'in yerine yeni bir div olarak yazabilir, token yerine hex değer kullanabilir. Bu yüzden guide'ın önerileri bu yazının konusuyla örtüşüyor: tekrar kullanılan her şey component olsun, component'ler Code Connect ile koda bağlansın, renk, boşluk ve köşe yarıçapı variable olsun, Auto Layout responsive niyeti taşısın, katmanlar anlamlı adlandırılsın ve büyük ekranlar yerine küçük parçalar seçilsin. MCP üzerinden üretilen kod da bu serideki ölçümlerden geçmeli: kontrast, state'ler, hedef boyutu, taşma.

Handoff Checklist: Pixel-perfect Değil, Token-perfect

"Pixel-perfect" hedefi tek bir genişlikte, tek bir temada ve tek bir state'te doğru olan bir ekran üretiyor; ölçümdeki kopyalanmış bar tam olarak buydu. Token-perfect hedef ise her değerin bir karara bağlı olduğu bir ekran: renk bir semantic token, boşluk bir spacing token, genişlik bir sizing niyeti. Tasarımı "ready for dev" saymadan önce bu serinin dokuz yazısından çıkan soruları sormak yeterli:

  • Bütün state'ler çizildi mi: hover, focus-visible, active, disabled, loading, error, selected (07)?
  • Boş, sonuç yok ve hata ekranları var mı ve her biri bir yol gösteriyor mu (07, 08)?
  • Bileşen dar ve geniş ekranda nasıl davranıyor; FILL, HUG ve FIXED niyeti açık mı, en dar genişlik 320 piksel mi (09)?
  • Her renk, boşluk ve köşe yarıçapı bir variable'a bağlı mı; bağlı olmayan değerlerin listesi boş mu (10, 11)?
  • Metin ve kontrollerin kontrastı ve dokunma hedefleri ölçüldü mü; dark tema ayrı bir mode olarak çizildi mi (04, 09)?
  • Form'larda label'lar, yardım metinleri ve hata mesajlarının metni yazıldı mı (06)?
  • Klavye sırası, focus'un nereye gideceği ve ekran okuyucu için not edilmesi gerekenler annotation olarak eklendi mi (07)?

Üretimde Dikkat

Tek bir kaynak seç. Token'ların kaynağı kod mu, tasarım dosyası mı? İkisi de olabilir, ama ikisi birden olamaz. Bookstore'da kaynak repodaki DTCG dosyaları; Figma variable'ları onlardan güncelleniyor ve script farkları raporluyor. Tersi de geçerli bir seçim, yeter ki yön tek olsun.

Figma'nın ve araçlarının koşulları sık değişiyor. Bu yazıdaki plan, seat ve sınır bilgileri Kasım 2026 tarihli; MCP server'ın yetenekleri ve fiyatlandırması beta süresince değişebilir. Bir ekibe süreç önermeden önce güncel dokümantasyona bakmak gerekiyor.

AI ile üretilen kodu, insan eliyle yazılmış kod gibi gözden geçir. Asistanın tasarım bağlamına erişmesi, ürettiği kodun erişilebilir, token'lı ve projenin component'lerini kullanan bir kod olduğu anlamına gelmiyor; bu serideki script'ler bunun kontrolünü otomatikleştirmek için iyi bir başlangıç.

Sık Düşülen Tuzaklar

Birincisi, Dev Mode'daki ölçüleri ve hex değerleri olduğu gibi kopyalamak. Sayı tek bir frame'de doğru; niyet (FILL, HUG, token) her ekranda.

İkincisi, tasarımda variable'a bağlanmamış değerleri kabul etmek. Bağlanmamış her değer, kodda bir magic number olarak geri dönüyor.

Üçüncüsü, tasarım ve kod token'larını iki ayrı kaynak olarak yaşatmak. Aradaki fark ancak biri ölçünce görünüyor; karşılaştırmayı otomatikleştir.

Dördüncüsü, Code Connect olmadan AI'dan component kodu beklemek. Model senin kütüphaneni bilmiyorsa tahmin ediyor.

Beşincisi, handoff'u tek bir ekran görüntüsüne indirgemek. State'ler, boş ve hata ekranları, responsive davranış ve erişilebilirlik notları da tasarımın parçası.

Küçük Bir Deneme

★☆☆ cart-bar.figma.json'da Checkout'un height ve cornerRadius değerlerini variable'a bağla: variables.figma.json'a button/min-height ve button/radius adında iki FLOAT variable ekle. Script'in "values not bound to a variable" satırının boşaldığını ve üretilen CSS'te iki yeni token'ın göründüğünü doğrula.

★★☆ Çeviriciye layoutWrap: WRAP ve counterAxisSpacing desteği ekle ve 09. yazıdaki kategori şeridini Auto Layout JSON'u olarak yaz. 320 piksel genişlikte şeridin satır atladığını ve satırlar arası boşluğun row-gap olarak geldiğini ölç.

★★★ Variable karşılaştırmasını ters yöne çevir: DTCG token'larından Figma REST API'sinin POST variables gövdesi biçiminde bir JSON üret ve blue/600 farkını kapatacak değişikliği bu gövdede göster. API'yi çağırmadan, yalnız üretilen gövdenin dokümante edilen alanlarla uyumunu kontrol et.

Seri burada bitiyor. On bir yazı boyunca Bookstore'un checkout'undan sepetine, kataloğundan token dosyalarına kadar her kararı bir ölçüme bağlamaya çalıştık: heuristic'ler, hiyerarşi, typography, renk ve kontrast, spacing, form'lar, state'ler, navigation, responsive tasarım, design system ve handoff. Buradan sonraki doğal adım, kriterlerin tam ve test edilebilir hâliyle Accessibility (a11y) serisi ve bu kararların kullanıcı üzerindeki etkisini ölçmeyi anlatan Analytics ve Ölçüm serisi.