Design token adalah kosakata bersama antara desainer dan developer. Token ini sudah ada dalam berbagai bentuk sejak era Salesforce Lightning — Style Dictionary, Theo, draf spesifikasi W3C Design Token Community Group. Yang berubah belakangan ini adalah token ini juga menjadi kosakata bersama antara codebase Anda dan AI coding agent.
Agen yang mengetahui color.accent = #d96a3a akan menggunakan nilai tersebut. Agen yang mendapat screenshot akan menebak "oranye hangat" dan menghasilkan sesuatu yang mendekati tapi salah. Perbedaan ini berlipat ganda di puluhan komponen.
figmascope mengekspor tokens.json sebagai bagian dari setiap context bundle. Artikel ini menjelaskan format secara detail, bagaimana figmascope mengambil token dari Figma, fallback frequency-inference untuk file tanpa Figma Variables, dan cara menghubungkan output ke framework umum. Untuk melihat bagaimana token cocok dalam alur ekspor lengkap, kunjungi aplikasi figmascope atau baca Figma to Cursor dan Figma to Claude Code.
Format tokens.json
figmascope menggunakan format yang terinspirasi dari W3C Design Token Community Group. Setiap token adalah objek dengan field $value dan $type, bersarang di bawah kunci kategori semantik:
{
"color": {
"surface": { "$value": "#f6f2ea", "$type": "color" },
"surface-2": { "$value": "#efe9dc", "$type": "color" },
"ink": { "$value": "#1f1d1a", "$type": "color" },
"ink-muted": { "$value": "#4a4641", "$type": "color" },
"accent": { "$value": "#d96a3a", "$type": "color" },
"accent-soft": { "$value": "#f2c7a8", "$type": "color" },
"good": { "$value": "#6a8f5a", "$type": "color" },
"warn": { "$value": "#c89a3a", "$type": "color" },
"bad": { "$value": "#b8553a", "$type": "color" }
},
"spacing": {
"1": { "$value": "4px", "$type": "dimension" },
"2": { "$value": "8px", "$type": "dimension" },
"3": { "$value": "12px", "$type": "dimension" },
"4": { "$value": "16px", "$type": "dimension" },
"6": { "$value": "24px", "$type": "dimension" },
"8": { "$value": "32px", "$type": "dimension" },
"12": { "$value": "48px", "$type": "dimension" },
"16": { "$value": "64px", "$type": "dimension" }
},
"radius": {
"sm": { "$value": "4px", "$type": "dimension" },
"md": { "$value": "8px", "$type": "dimension" },
"lg": { "$value": "16px", "$type": "dimension" },
"full": { "$value": "9999px", "$type": "dimension" }
},
"typography": {
"body": {
"fontFamily": { "$value": "Inter", "$type": "fontFamily" },
"fontSize": { "$value": "14px", "$type": "dimension" },
"fontWeight": { "$value": 400, "$type": "number" },
"lineHeight": { "$value": 1.45, "$type": "number" }
},
"heading": {
"sm": {
"fontFamily": { "$value": "Inter", "$type": "fontFamily" },
"fontSize": { "$value": "18px", "$type": "dimension" },
"fontWeight": { "$value": 600, "$type": "number" },
"lineHeight": { "$value": 1.25, "$type": "number" }
}
},
"mono": {
"fontFamily": { "$value": "JetBrains Mono", "$type": "fontFamily" },
"fontSize": { "$value": "13px", "$type": "dimension" },
"fontWeight": { "$value": 400, "$type": "number" }
}
}
}
Mengapa mirip W3C tapi tidak persis mengikuti spesifikasi?
Spesifikasi W3C Design Token Community Group masih berupa draf. figmascope mengikuti konvensi inti ($value, $type, grup bersarang) tetapi tidak mengimplementasikan semua kasus tepi seperti tipe komposit dan rantai resolusi alias. Outputnya cukup stabil untuk dikonsumsi oleh Style Dictionary, traversal JSON langsung, atau language model — yang merupakan konsumen utama.
Tipe token yang digunakan
| $type | Kategori | Format $value | Contoh |
|---|---|---|---|
color |
color | string hex | "#d96a3a" |
dimension |
spacing, radius | string CSS dengan satuan | "16px" |
fontFamily |
typography | string nama font | "Inter" |
number |
typography | angka tanpa satuan | 400, 1.45 |
Warna selalu dioutput sebagai string hex. Jika sumber Figma menggunakan RGBA dengan opasitas tidak penuh, saluran alfa dipertahankan dalam hex 8 digit (#d96a3a80).
Cara figmascope mengambil token
figmascope menggunakan strategi pengambilan dua tingkat. Figma Variables adalah sumber yang lebih diutamakan; frequency inference adalah fallback.
Tingkat 1: Figma Variables
Jika file Figma memiliki Variables yang didefinisikan (sistem token native Figma, tersedia di paket Professional dan Organization), figmascope membacanya melalui endpoint /v1/files/:key/variables/local REST API. Nama variabel digunakan sebagai kunci token, dinormalisasi ke kebab-case. Mode diruntuhkan ke mode default kecuali file hanya memiliki satu mode, di mana nilai mode tersebut digunakan langsung.
Koleksi variabel dipetakan ke kunci kategori tingkat atas di tokens.json. Koleksi bernama "Color" menghasilkan tokens.color.*; "Spacing" menghasilkan tokens.spacing.*. Jika file Figma Anda menggunakan nama koleksi non-standar, figmascope mencoba menyimpulkan kategori dari tipe yang diselesaikan variabel.
Tingkat 2: Frequency inference
Banyak file Figma — terutama yang lama atau file dari klien yang belum mengadopsi Variables — tidak memiliki definisi variabel. figmascope menangani ini dengan menelusuri seluruh node tree dan membangun histogram frekuensi fill color, nilai spacing, corner radius, dan properti tipografi.
Nilai yang muncul di atas ambang frekuensi menjadi token kandidat. Token diberi nama berdasarkan kategori dan indeks sekuensial (color.0, color.1...) kecuali nama yang dapat dibaca manusia dapat disimpulkan dari cara nilai digunakan (misalnya, warna yang hanya digunakan di background di beberapa frame menjadi color.surface).
Manifes _meta.json mencatat tokensSource sebagai "variables" atau "inferred", sehingga prompt agen Anda dapat mencatat ketika inference digunakan:
// _meta.json — inferred fallback
{
"tokensSource": "inferred",
"warnings": [
{
"code": "tokens-inferred",
"message": "No Figma Variables found. Tokens were inferred from usage frequency."
}
]
}
Token yang disimpulkan berguna tetapi tidak otoritatif. Perlakukan sebagai titik awal, bukan spesifikasi sistem desain.
Referensi token dalam layout IR
File IR per-layar (screens/*.json) mereferensikan token berdasarkan jalur menggunakan string $ref daripada menyematkan nilai mentah. Ini menjaga IR tetap ringkas dan memastikan agen selalu menyelesaikan nilai dari satu sumber kebenaran:
{
"kind": "stack",
"name": "PrimaryButton",
"direction": "horizontal",
"gap": { "$ref": "spacing.2" },
"padding": {
"top": 10, "right": 16, "bottom": 10, "left": 16
},
"background": { "$ref": "color.accent" },
"radius": { "$ref": "radius.sm" },
"children": [
{
"kind": "leaf",
"name": "ButtonLabel",
"type": "text",
"style": { "$ref": "typography.body" },
"color": { "$ref": "color.surface" }
}
]
}
Agen yang memproses node ini menyelesaikan color.accent ke #d96a3a dan spacing.2 ke 8px dari file tokens.json paralel. Tidak ada ambiguitas, tidak ada halusinasi nilai.
Lihat penjelasan per-screen IR untuk dokumentasi skema node lengkap.
Menggunakan tokens.json dengan Style Dictionary
Output figmascope kompatibel dengan Style Dictionary dengan konfigurasi minimal. Karena sudah menggunakan konvensi $value / $type, Anda dapat mengarahkan Style Dictionary langsung ke tokens.json:
// style-dictionary.config.js
module.exports = {
source: ['design/tokens.json'],
platforms: {
css: {
transformGroup: 'css',
prefix: 'fs',
buildPath: 'src/styles/',
files: [{ destination: 'tokens.css', format: 'css/variables' }]
},
js: {
transformGroup: 'js',
buildPath: 'src/',
files: [{ destination: 'tokens.js', format: 'javascript/es6' }]
}
}
};
Menjalankan style-dictionary build akan menghasilkan CSS custom properties dan ekspor ES module dari file sumber yang sama yang digunakan agen.
Menggunakan tokens.json dengan Tailwind
Sebuah script kecil mengkonversi tokens.json ke ekstensi tema Tailwind. Strukturnya cukup datar untuk ditelusuri tanpa rekursi pada kasus umum:
// scripts/tokens-to-tailwind.js
const fs = require('fs');
const tokens = JSON.parse(fs.readFileSync('design/tokens.json', 'utf8'));
function flattenGroup(group) {
return Object.fromEntries(
Object.entries(group).map(([k, v]) => [k, v.$value])
);
}
const extend = {
colors: flattenGroup(tokens.color),
spacing: flattenGroup(tokens.spacing),
borderRadius: flattenGroup(tokens.radius),
};
console.log(JSON.stringify(extend, null, 2));
node scripts/tokens-to-tailwind.js > design/tailwind-extend.json
Kemudian di tailwind.config.ts:
import extend from './design/tailwind-extend.json';
export default {
content: ['./src/**/*.{ts,tsx}'],
theme: { extend },
};
Menggunakan tokens.json dengan Jetpack Compose
Untuk proyek Android, struktur token dipetakan dengan bersih ke object Kotlin. Anda dapat membuatnya secara terprogram atau meminta Claude Code melakukannya. Untuk token warna:
// Generated from design/tokens.json
object DesignTokens {
object Color {
val surface = Color(0xFFF6F2EA)
val ink = Color(0xFF1F1D1A)
val accent = Color(0xFFD96A3A)
val accentSoft = Color(0xFFF2C7A8)
}
object Spacing {
val s1 = 4.dp
val s2 = 8.dp
val s4 = 16.dp
val s8 = 32.dp
}
}
Lihat Jetpack Compose dari Figma untuk panduan lengkap termasuk integrasi MaterialTheme.
Apa yang tidak ada dalam tokens.json
Mengetahui batasan ruang lingkup membantu menetapkan ekspektasi yang tepat:
- Shadow — figmascope saat ini tidak mengekspor token drop-shadow atau inner-shadow. Nilai shadow muncul secara inline pada node di IR jika ada.
- Gradien — fill gradien diekspor apa adanya pada leaf node di IR, bukan sebagai token bernama.
- Animasi — timing, easing, dan nilai transisi berada di luar ruang lingkup. Dukungan animasi Figma ada di mode Prototype, yang tidak dibaca figmascope.
- Breakpoint — constraint responsif bukan konsep Figma di tingkat variabel; keputusan desain terpisah diperlukan.
Array warnings di _meta.json akan mencatat nilai yang tidak dapat diekspor dengan bersih. Tinjau sebelum menyerahkan bundle ke agen.
Cara nama token diturunkan
Ketika figmascope membaca Figma Variables, nama variabel di Figma menjadi kunci token. Variabel bernama Colors/Surface/Primary dalam koleksi bernama Color menjadi tokens.color.surface.primary di tokens.json — pemisah jalur adalah / di Figma, . di kunci bersarang JSON.
Figma mengizinkan nama variabel dengan spasi, huruf kapital, dan karakter khusus. figmascope menormalisasi ini:
- Spasi menjadi tanda hubung:
Primary Surface→primary-surface - Huruf kapital diubah ke huruf kecil:
AccentOrange→accent-orange - Karakter kontrol dan tanda Unicode bidi dihilangkan melalui
sanitizeName - Skrip Kiril dan skrip non-Latin lainnya ditranslitrasi untuk kompatibilitas slug
Langkah transliterasi penting untuk tim internasional. Tim desain Ukraina yang menggunakan nama variabel Kiril seperti Фон (background) mendapatkan kunci ASCII yang stabil (fon) di output, yang dapat digunakan dalam nama kelas CSS dan JSON tanpa masalah encoding. Nama asli dipertahankan sebagai field $description jika ada dalam metadata Figma Variable.
Memeriksa cakupan token sebelum codegen
Sebelum menyerahkan bundle ke agen, ada baiknya memverifikasi bahwa cakupan token terlihat wajar. Script Node cepat yang memeriksa apakah semua nilai warna yang direferensikan dalam screen IR diselesaikan ke entri di tokens.json:
// scripts/check-token-coverage.js
const fs = require('fs');
const glob = require('glob');
const tokens = JSON.parse(fs.readFileSync('design/tokens.json', 'utf8'));
const screenFiles = glob.sync('design/screens/*.json');
function getRef(obj) {
const refs = [];
if (obj && typeof obj === 'object') {
if (obj.$ref) refs.push(obj.$ref);
for (const v of Object.values(obj)) refs.push(...getRef(v));
}
return refs;
}
function resolveRef(ref, tokens) {
return ref.split('.').reduce((o, k) => o?.[k], tokens);
}
let missing = 0;
for (const file of screenFiles) {
const screen = JSON.parse(fs.readFileSync(file, 'utf8'));
for (const ref of getRef(screen)) {
if (!resolveRef(ref, tokens)) {
console.error(`Missing token: ${ref} (in ${file})`);
missing++;
}
}
}
if (missing === 0) console.log('All token refs resolve.');
else console.error(`${missing} unresolved token refs.`);
Nol referensi yang hilang berarti agen dapat menyelesaikan setiap $ref dalam layout IR tanpa membuat nilai sendiri. Jika ada referensi yang hilang, biasanya berarti file Figma berubah setelah bundle diekspor — jalankan ulang figmascope untuk mendapatkan ekspor baru. Anda juga dapat mengunjungi blog figmascope untuk tips lebih lanjut tentang mempertahankan cakupan token di seluruh iterasi desain.