Konde Design Framework

i18n 是你的翻譯。
KDF 是你的設計。
兩者都住在 JSON 裡。

專為伺服器端 Web 應用程式及 AI 輔助 UI 打造的 JSON 設計協調層。所有可重複的決策 — 排版、間距、字體、元件樣式 — 都集中在一個事實來源,讓你的 AI 代理讀取,不再需要從各種檔案、頁面跟過往紀錄中到處拼湊。

看看它是怎麼運作的
kdf / homepage.json → 渲染結果
kdf/homepage.json
{
  "$layout": ["hero", "footer"],
  "hero": {
    "wrapper": "mx-auto max-w-6xl px-6 py-20",
    "title":   "@typography.h1",
    "cta-primary": "@button.cta"
  }
}
data-kdf="hero.title"
與 AI 一起打造並發布產品。
data-kdf="hero.body"

單一的事實來源,讓每個頁面、元件與 AI 會話都保持設計一致性。

data-kdf="hero.cta-primary"
開始使用 →

JSON 負責定義 · 程式碼負責渲染 · data-kdf 互相映射

授權
MIT
執行環境
Node 檔案系統
依賴套件
零 Runtime 依賴
已測試
Next · Astro · Hono
01 — 痛點

設計在你的元件裡
漸漸失控。

當 class 名稱只存在於 .tsx 檔案裡時,每個頁面的設計就會慢慢分岔。如果只有單一真人開發者在維護還過得去 — 但一旦讓 AI 代理開始動 UI,這一切就會變得不堪一擊。

沒用 kdf 的情況 · 散落在各個檔案中
<section className="mx-auto max-w-6xl px-6 py-20">
  <h1 className="text-5xl font-semibold tracking-tight">
  // …and again, slightly different, on the next page

同一個按鈕默默長出了五種變體,每個頁面的間距都不太一樣。而且每次新的 AI 代理對話,都得從頭重新摸索一次設計規則。

結果就是
  • AI 代理自己發揮創意亂套顏色、間距、字體跟排版。
  • 使用者每次都得在聊天室裡重新糾正它。
  • 每次修改都得在元件檔裡大海撈針。
  • 不斷重複的對話讓最初的設計理念蕩然無存。

→ 永無止境的"大一點" · "藍一點" · "往左移"來回修改

02 — 解決方案

讓設計明確化。

KDF 為設計做的事,就跟 i18n 為文字做的事一樣:它把可重複的決策從元件檔案中抽離,移到 JSON 裡。渲染出來的 UI 依然用的是一般的 CSS — 改變的只有它的歸屬權。

1 — 在 JSON 中定義
{
  "hero": {
    "title": "text-5xl font-semibold tracking-tight"
  }
}
2 — 在程式碼中渲染
const d = getDesign("homepage");

<h1 data-kdf="hero.title" className={d("hero.title")}>
JSON 負責定義
用一個檔案掌控設計方向。當使用者需要精確控制時,就直接修改它。
程式碼負責渲染
你的元件讀取 Token,並用一般 CSS 渲染出核准的設計 — 底層完全沒有黑魔法。
AI 代理負責實作
AI 代理從 JSON 讀取資訊來建構 UI,不再瞎猜。沒有憑空捏造的間距、顏色、字體或區塊順序。
使用者調整 JSON
只要在來源修改一次,就不用在每次對話裡反覆描述一樣的視覺調整。
03 — 不是元件庫

元件庫告訴你這是什麼,
KDF 告訴你這是哪一個.

設計庫會給你一個 Button,KDF 則會告訴你這是 homepage.hero.cta-primary,被渲染成一個 Button,並套用了這個 Token 的樣式。它補足了元件庫漏掉的那塊拼圖 — 將元素與設計決策連結起來。

 設計庫KDF
它說了什麼「這是一個 Button。」「這是 homepage 上的 hero.cta-primary。」
對應關係通用的元件,可能會有無數種覆寫方式。一個元素對應一個設計決策 (Key)。
可追溯性無法從元素精確追溯到設計決策。data-kdf 將每個 DOM 節點精準指向它在 JSON 中的路徑。
疊加於 shadcn · Bootstrap · Chakra · Tailwind · plain CSS · 甚至是你們自家的系統之上 — KDF 從來都不是要取代它們。
04 — 詞彙表

六個符號。
一套語法。

KDF 儲存 class 名稱、共用參考、區塊順序及 CSS 自訂屬性。它絕對不存業務邏輯、事件處理器、資料請求、權限或是無障礙 (a11y) 行為。

data-kdf
映射

每個使用 Token 的元素都帶有對應的路徑。DOM 節點可以直接追溯回 JSON — 方便掃描器、測試及 AI 代理檢查。

data-kdf="hero.title"
d(path)
存取器

將路徑解析為它的 className 字串。d.css() 則會回傳 CSS 自訂屬性物件。

className={d("hero.title")}
@
共用參考

指向 shared/ 中可重複使用的 Token。參考可以串聯,並加上額外的 class 來擴充。

"@button.cta" shadow-xl
$layout
順序與可見度

一個陣列,包含區塊的 key。列出的區塊會依序渲染;沒被列出的則會被主應用程式隱藏。

["hero", "features", "footer"]
$
元件識別

給 AI 代理跟主機端工具看的 Metadata — 說明是哪個元件渲染了這個 Token,還有變體與大小提示。

"$": "Button"
css
自訂屬性

無法用共用 class 表達的值,透過 d.css() 作為內聯樣式 (inline style) 變數來套用。

{ "--kdf-accent": "#4F46E5" }
05 — 架構

共用預設值,
頁面級覆寫。

設計 Token 住在兩個地方:可重複使用的預設值放在 shared/,而各頁面專屬的組合只會覆寫它需要的部分。有兩個完全由你掌控的 CSS 檔,負責處理首次繪製 (first paint) 以及提供救急用的 escape hatches (特殊覆寫)。

專案架構
kdf/
  shared/
    button.json      ← reusable defaults
    card.json
    color.json
    typography.json
  homepage.json      ← page composition
  konde-server.css   ← critical, first paint
  konde.css          ← non-critical tweaks
多層次聯集

@button.cta 這樣的參考,會依序從該頁面的 shared/、父層 shared/,最後到頁面 Token 進行解析。模板只需覆寫需要的部分,剩下的全部繼承。

預設輕量

設計在伺服器端解析,瀏覽器收到的是組裝好的 class 字串。關鍵 CSS 會在首次繪製時載入,剩下的才隨後載入 — 不會把渲染成本丟給效能較差的裝置。

兩個由你掌控的 CSS 檔 · 兩個載入時機
konde-server.css
關鍵樣式 · 首次繪製

由 App 引入,讓設計變數跟防閃爍 (no-FOUC) 覆寫在畫面首次繪製時就生效 — 在任何東西閃爍前搞定。

/* konde-server.css */
:root { --kdf-primary: #1F8F47; }
[data-kdf="hero.slider"] { display: none; }
konde.css
非關鍵樣式 · App CSS 之後

在框架與 App 的 CSS 後載入,用來做微調、實驗和救急覆寫 (escape hatches) — 這些精細調整從來都不該阻礙畫面的首次繪製。

/* konde.css */
[data-kdf="hero.title"] { letter-spacing: -0.02em; }
[data-kdf="hero.wrapper"] { gap: 3rem; }

→ KDF 只會建立這兩個檔案一次,永遠不會覆寫它們。Plugin 會透過環境變數暴露它們的路徑,你的 App 自己去引入就好;它不會偷偷塞任何東西給你。

06 — 多重模板

切換設計
就像切換語言一樣。

就跟 i18n 切換語言一樣,KDF 可以切換設計模板。同一個 App、同一個元件、同一套程式碼 — 只要把 KDF_DIR 指向另一個設計資料夾,整個外觀就會煥然一新。

designs/ — 兩個模板,一個 App
designs/
  lander/
    shared/
    homepage.json
  newlander/
    shared/
    homepage.json
// next.config.ts
withKDF({ dir: "./designs/lander" })(nextConfig);
$layout 不用動到元件,就能重新排序或隱藏區塊。
@button 透過共用 Token 一次改掉所有 CTA 的樣式。
KDF_DIR 由主機端 (host) 刻意決定,輕鬆切換整套設計模板。
07 — 執行階段 API

在伺服器端解析,
將字串往下傳。

KDF 核心會從硬碟讀取 JSON,所以它跑在伺服器端:包含 Next.js Server Components、Astro 渲染和 Hono handlers。在那裡把 class 解析好,再把純字串傳給客戶端元件。

伺服器端元件
import { getDesign, cn } from "@kondeio/kdf";

const d = getDesign("homepage");

<button data-kdf="hero.cta" className={cn(d("hero.cta"), isActive)}>Start</button>
d("hero.title")

→ 解析好的 className 字串

d.css("hero.title")

→ CSS 自訂屬性物件

cn · cx · dedupeClasses

合併條件式 class、濾掉 falsy 值、去除重複 — 預設是純字串處理 (semantic-free)。

cache: auto · always · none

Production 環境會使用快取;Dev 環境會透過 mtime 和檔案大小重新驗證。

08 — 天生相容

它穩穩坐在
你的技術棧上。

樣式處理 — 只存 CLASS 名稱,不存 CSS

TailwindshadcnBootstrapChakraCSS ModulesPlain CSSYour own system

KDF 不是 CSS 引擎。Token 裡面放的是你樣式系統看得懂的 class 字串。如果你的框架會掃描原始碼,把 JSON 也加進去:@source "../kdf/**/*.json"

執行環境 — 伺服器端 JAVASCRIPT

Next.js 已測試 · 提供 Plugin
Astro 已測試
Hono 已測試
開始使用

裝一次就好,
剩下的 Init 幫你搞定。

安裝的同時,如果沒有 kdf/ 資料夾,它會順便幫你建出一個初始版本。原有的檔案絕對不會被覆寫。

$npm install @kondeio/kdf
$pnpm add @kondeio/kdf
$bun add @kondeio/kdf
$npm exec -- kdf init # 手動建立結構
next.config.ts
import withKDF from "@kondeio/kdf/plugin";

export default withKDF({ dir: "./designs" })(nextConfig);