Ya, Anda dapat mendeskripsikan sebuah tema dalam Bahasa Inggris dan mendapatkan design system yang berfungsi. Masalahnya adalah deskripsi dalam Bahasa Inggris itu bukan prompt. Ia adalah file sumber. Dan seperti file sumber lainnya, ia memerlukan compiler, sistem tipe, dan test.

Jika Anda memperlakukannya seperti query chatbot, Anda akan mendapatkan palet warna yang berbeda pada hari Selasa dibanding hari Senin. Jika Anda memperlakukannya seperti DSL dengan konteks terbatas dan schema yang ketat, Anda mendapatkan token yang dapat direproduksi yang dapat dikonsumsi oleh design system Anda.

Design token adalah masalah sinkronisasi, bukan masalah kreatif

Sebagian besar tim tidak kesulitan memilih warna. Mereka kesulitan menjaga konsistensi warna antara Figma, variabel CSS, dan component library. Workflow tipikal terlihat seperti ini: seorang desainer memperbarui kode hex dalam style guide, seorang pengembang menyalinnya ke file JSON, pengembang lain mereferensikan kunci yang salah dalam komponen React, dan tiga bulan kemudian Anda memiliki #1a1a2e di satu tempat dan #1b1b2f di tempat lain.

Rasa sakit yang sesungguhnya adalah handoff. Figma bukan kode. JSON bukan alat desain. Bahasa Inggris berada di tengah. Ia adalah satu-satunya format yang dapat dibaca oleh desainer dan pengembang tanpa pelatihan.

Pertanyaannya bukan apakah LLM dapat mengubah Bahasa Inggris menjadi kode hex. Pertanyaannya adalah apakah Anda dapat mengubah proses tersebut menjadi sesuatu yang cukup andal untuk dijalankan di CI.

Bagaimana theme-to-code sebenarnya bekerja

Arsitekturnya lugas. Anda menulis manifest tema singkat dalam Bahasa Inggris sederhana. Sebuah script memberikannya kepada LLM dengan format output yang dibatasi. LLM mengembalikan token terstruktur. Anda menulis token tersebut ke disk, melakukan type-check, dan melakukan commit.

Berikut adalah pipeline-nya:

  1. Manifest: File .txt atau .md yang mendeskripsikan tema dalam prosa.
  2. Schema: Definisi Zod (atau JSON Schema) yang harus dikembalikan oleh LLM.
  3. Compiler: Script yang membaca manifest, memanggil LLM dengan output terstruktur, dan menulis tokens.json.
  4. Gate: Test yang gagal jika token yang dihasilkan menyimpang dari snapshot atau melanggar constraint.

Kuncinya adalah langkah ketiga. Anda tidak meminta model untuk “membuat tema gelap.” Anda memintanya untuk mengisi schema. Itu mengubah tugas menulis kreatif menjadi tugas ekstraksi data terstruktur, yang merupakan kekuatan LLM yang jauh lebih besar.

Compiler yang berfungsi dalam TypeScript

Berikut adalah implementasi minimal namun lengkap. Ia membaca deskripsi tema, memanggil OpenAI dengan schema Zod, dan menulis hasilnya ke file JSON.

import { z } from "zod";
import { zodToJsonSchema } from "zod-to-json-schema";
import OpenAI from "openai";

// 1. Define the bounded context: only these tokens exist
const TokenSchema = z.object({
  name: z.string(),
  colors: z.object({
    background: z.string().regex(/^#[0-9a-f]{6}$/i),
    surface: z.string().regex(/^#[0-9a-f]{6}$/i),
    primary: z.string().regex(/^#[0-9a-f]{6}$/i),
    text: z.string().regex(/^#[0-9a-f]{6}$/i),
    muted: z.string().regex(/^#[0-9a-f]{6}$/i),
  }),
  spacing: z.object({
    unit: z.number().min(4).max(16),
    scale: z.array(z.number()).length(4),
  }),
  radii: z.object({
    sm: z.number(),
    md: z.number(),
    lg: z.number(),
  }),
});

type TokenSet = z.infer<typeof TokenSchema>;

// 2. The compiler
async function compileTheme(
  description: string,
  apiKey: string
): Promise<TokenSet> {
  const client = new OpenAI({ apiKey });

  const completion = await client.chat.completions.create({
    model: "gpt-4o",
    messages: [
      {
        role: "system",
        content:
          "You are a design-token compiler. " +
          "Convert the user's theme description into the exact JSON schema provided. " +
          "All colors must be valid 6-digit hex. " +
          "The spacing unit must be a multiple of 4. " +
          "The scale array must have exactly 4 values.",
      },
      {
        role: "user",
        content: description,
      },
    ],
    response_format: {
      type: "json_schema",
      json_schema: {
        name: "theme_tokens",
        strict: true,
        schema: zodToJsonSchema(TokenSchema),
      },
    },
  });

  const raw = JSON.parse(completion.choices[0].message.content!);
  return TokenSchema.parse(raw);
}

// 3. CLI entrypoint
async function main() {
  const description = await Bun.file("theme.manifest.txt").text();
  const tokens = await compileTheme(description, process.env.OPENAI_API_KEY!);
  await Bun.write("tokens.json", JSON.stringify(tokens, null, 2));
  console.log("Compiled theme:", tokens.name);
}

main();

Anda memerlukan zod, openai, dan zod-to-json-schema sebagai dependency. Script ini mengasumsikan Anda menggunakan Bun, tetapi mengganti Bun.file dan Bun.write dengan fs.promises adalah hal yang trivial.

Trade-off yang tidak dapat Anda abaikan

Ini berfungsi, tetapi tidak gratis.

Determinisme. Bahkan dengan temperature diatur ke nol dan output terstruktur diaktifkan, deskripsi yang sama dapat menghasilkan kode hex yang sedikit berbeda di berbagai versi model. Jika Anda menjalankan ulang compiler setelah pembaruan OpenAI, snapshot test Anda mungkin gagal. Anda harus melakukan commit terhadap tokens.json yang dihasilkan dan hanya mengompilasi ulang ketika manifest berubah.

Latensi. Memanggil LLM dalam langkah build Anda menambahkan detik, kadang puluhan detik. Jangan mengompilasi tema pada setiap hot reload. Jalankan compiler sebagai pre-commit hook atau di CI ketika file manifest berubah.

Ketegaran schema. LLM tidak dapat menemukan kategori token baru. Jika design system Anda nanti membutuhkan elevation.shadows.xl, Anda harus memperbarui schema Zod, system prompt, dan compiler sebelum model dapat mengeluarkannya. Itu adalah fitur, bukan bug. Itu menjaga DSL tetap terbatas.

Aksesibilitas. LLM tidak tahu apakah warna primary Anda terhadap background Anda memenuhi rasio kontras WCAG. Anda harus memvalidasi token yang dihasilkan dengan pemeriksaan terpisah. Tambahkan ini setelah pemanggilan TokenSchema.parse:

function contrastRatio(hex1: string, hex2: string): number {
  // WCAG relative luminance calculation
  const lum = (hex: string) => {
    const rgb = parseInt(hex.slice(1), 16);
    const [r, g, b] = [(rgb >> 16) & 0xff, (rgb >> 8) & 0xff, rgb & 0xff];
    const f = (c: number) => {
      c /= 255;
      return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
    };
    return 0.2126 * f(r) + 0.7152 * f(g) + 0.0722 * f(b);
  };
  const l1 = lum(hex1) + 0.05;
  const l2 = lum(hex2) + 0.05;
  return l1 > l2 ? l1 / l2 : l2 / l1;
}

// After parsing tokens
const ratio = contrastRatio(tokens.colors.primary, tokens.colors.background);
if (ratio < 4.5) {
  throw new Error(`Contrast ratio ${ratio.toFixed(2)} fails WCAG AA`);
}

Ketika ini gagal: masalah interaksi

Pendekatan ini berfungsi dengan sangat baik untuk palet warna, spacing scale, dan keluarga tipografi. Ia gagal ketika token berinteraksi dengan cara yang sulit dideskripsikan dalam prosa.

Semantic token adalah perangkap klasik. Anda mungkin menulis “gunakan warna primary untuk link dan button.” Bagaimana dengan button yang dinonaktifkan? Bagaimana dengan link di dalam banner peringatan yang sudah menggunakan warna primary? Ini bukan keputusan di tingkat tema. Ini adalah aturan di tingkat komponen, dan mereka termasuk dalam component library Anda, bukan dalam file manifest.

Pertahankan manifest terbatas pada primitive token. Biarkan komponen Anda menangani semantik.

Pertanyaan yang sering diajukan

Apa itu DSL konteks terbatas? Bahasa kecil dengan cakupan sempit. Dalam hal ini, “bahasa” tersebut adalah prosa Bahasa Inggris yang hanya mendeskripsikan design token, yang diatur oleh schema yang ketat.

Apakah deskripsi yang sama akan selalu menghasilkan token yang sama? Tidak selalu. Output LLM bervariasi di berbagai versi model dan penyedia. Lakukan commit terhadap token yang dihasilkan dan gunakan snapshot test untuk mendeteksi drift.

Dapatkah saya menggunakan ini untuk gaya di tingkat komponen? Tidak. Manifest hanya boleh mendefinisikan primitive token seperti warna dan spacing. Semantik komponen termasuk dalam component library Anda.

Apakah saya memerlukan OpenAI, atau apakah model lain akan berfungsi? Setiap model yang mendukung output JSON terstruktur dan mengikuti system prompt akan berfungsi. Model lokal seperti Llama 3.3 adalah pilihan yang layak jika Anda memiliki hardware yang cukup untuk menjalankannya dengan cukup cepat untuk build pipeline Anda.

Mulai dengan manifest sepuluh baris dan schema yang ketat

Pilih satu konteks terbatas, seperti landing page marketing atau admin dashboard. Tulis manifest sepuluh baris, definisikan schema Zod tanpa field opsional, dan hasilkan file token pertama Anda. Lakukan commit terhadap output. Tulis test yang mengompilasi ulang manifest dan membandingkannya dengan snapshot yang telah di-commit.

Jika snapshot drift tanpa manifest berubah, compiler Anda tidak deterministik. Perbaiki system prompt atau pin versi model hingga menjadi deterministik.

Design system Anda tidak memerlukan plugin Figma lainnya. Ia memerlukan sumber kebenaran yang dapat dibaca oleh desainer dan pengembang. Bahasa Inggris sederhana dapat dibaca. Schema membuatnya andal.