Konde Design Framework

i18n lo phần dịch thuật.
KDF lo phần thiết kế.
Cả hai đều nằm gọn trong JSON.

Một lớp điều phối thiết kế bằng JSON dành cho web app server-side và UI do AI hỗ trợ. Các quyết định lặp lại — layout, khoảng cách, typography, component style — giờ đều nằm chung một chỗ để agent đọc được, thay vì mò mẫm qua từng file, từng trang hay lục lại các cuộc trò chuyện cũ.

Xem cách hoạt động
kdf / homepage.json → đã render
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"
Build và ship app với AI.
data-kdf="hero.body"

Một nguồn chân lý duy nhất giúp giữ cho mọi trang, mọi component, và mọi phiên làm việc của agent luôn đồng nhất với nhau.

data-kdf="hero.cta-primary"
Bắt đầu ngay →

JSON định nghĩa · code render · data-kdf map trở lại

Giấy phép
MIT
Runtime
Node Filesystem
Dependencies
Zero Runtime
Tested với
Next · Astro · Hono
01 — Vấn đề

Thiết kế bị lệch pha
trong các component.

Khi tên class chỉ nằm chết trong các file .tsx, các trang dần sẽ lệch pha nhau. Kiểu đó thì ổn nếu chỉ có mỗi con người code — nhưng sẽ rất mong manh ngay khi AI nhảy vào can thiệp giao diện.

không có kdf · vương vãi khắp các file
<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

Cùng một cái nút mà tự nhiên đẻ ra 5 phiên bản. Khoảng cách thì mỗi trang mỗi kiểu. Mỗi lần mở phiên mới là agent lại phải học lại luật từ đầu.

HẬU QUẢ LÀ
  • Agent tự phăng ra đủ thứ màu sắc, khoảng cách, typography và layout.
  • Lần nào người dùng cũng phải hì hục sửa lại giao diện thông qua chat.
  • Mỗi lần thay đổi là một lần bới tung các file component lên.
  • Chat qua nhiều phiên cũng rơi rụng dần ý đồ thiết kế ban đầu.

→ những vòng lặp "to lên tí" · "xanh hơn xíu" · "kéo qua trái" không hồi kết

02 — Giải pháp

Làm cho thiết kế trở nên rành mạch.

KDF làm với thiết kế y hệt cách i18n làm với chữ: bốc các quyết định lặp lại ra khỏi component rồi nhét vào JSON. UI lúc render vẫn dùng CSS bình thường — cái thay đổi ở đây là quyền kiểm soát thuộc về ai.

1 — định nghĩa trong json
{
  "hero": {
    "title": "text-5xl font-semibold tracking-tight"
  }
}
2 — render trong code
const d = getDesign("homepage");

<h1 data-kdf="hero.title" className={d("hero.title")}>
JSON định nghĩa
Chỉ một file nắm quyền định hướng thiết kế. Bạn cứ vào đó sửa trực tiếp khi cần tinh chỉnh siêu chi tiết.
Code render
Component đọc token ra rồi render theo đúng thiết kế được duyệt bằng CSS bình thường — chả có phép thuật ngầm nào ở đây cả.
Agent thi hành
Agent build UI từ JSON thay vì đoán mò. Cấm tiệt chuyện tự chế khoảng cách, màu sắc, font chữ hay đổi thứ tự section.
Người dùng chỉnh JSON
Chỉ việc sửa source đúng một lần thay vì chat đi chat lại cùng một yêu cầu cho mỗi phiên làm việc.
03 — Không phải thư viện component

Thư viện thì bảo đó là gì.
KDF thì bảo đó là cái nào.

Thư viện thiết kế quăng cho bạn cái Button. KDF thì cho bạn biết cái đó là homepage.hero.cta-primary, được render thành Button, và xài style của token này. Nó lấp đầy một chỗ trống quan trọng mà các thư viện hay bỏ sót — map từ element đến đúng quyết định thiết kế.

 Thư viện thiết kếKDF
Ý nghĩa"Đây là cái Button.""Đây là cái hero.cta-primary ở trang homepage."
MappingComponent dùng chung, có thể override bằng cả chục cách.Một element luôn map chính xác với một key thiết kế.
Khả năng truy xuấtKhông có cách nào map ngược từ element về quyết định ban đầu.data-kdf trỏ thẳng mọi DOM node về đúng JSON path của nó.
Nằm ở tầng trên shadcn · Bootstrap · Chakra · Tailwind · CSS thuần · hay hệ thống riêng của bạn — KDF sinh ra không phải để thay thế mấy cái này.
04 — Từ vựng

Sáu ký hiệu.
Một ngữ pháp.

KDF chỉ lưu tên class, các reference dùng chung, thứ tự section và CSS custom properties. Tuyệt đối không chứa business logic, event handler, lấy dữ liệu, quyền hạn hay tính năng accessibility.

data-kdf
Bản đồ

Mỗi element xài token đều cõng theo một path tương ứng. Các DOM node truy ngược thẳng về JSON — cực tiện cho bot quét, test và cho agent kiểm tra lại.

data-kdf="hero.title"
d(path)
Trình truy xuất

Phân giải path thành string className. Còn d.css() sẽ trả về cục CSS custom properties.

className={d("hero.title")}
@
Reference dùng chung

Trỏ đến một token xài lại được trong thư mục shared/. Các ref có thể nối tiếp nhau và mở rộng bằng cách chèn class.

"@button.cta" shadow-xl
$layout
Thứ tự & hiển thị

Một array chứa các key của section. Nằm trong list thì render theo thứ tự; không có thì app sẽ tự động giấu đi.

["hero", "features", "footer"]
$
Định danh component

Metadata dành cho agent và tool của host — báo cho biết component nào đang render token này, kèm theo các hint về size và biến thể.

"$": "Button"
css
Thuộc tính tuỳ chỉnh

Các giá trị không thể gom thành class dùng lại sẽ được nhét vào inline style variable thông qua hàm d.css().

{ "--kdf-accent": "#4F46E5" }
05 — Kiến trúc

Mặc định dùng chung.
Override từng trang.

Design token sống ở hai nơi: các token mặc định có thể xài lại nằm ở shared/, và một phần để override cục bộ cho những chỗ cần thiết. Có thêm hai file CSS riêng biệt lo phần first paint và giải quyết các case hóc búa.

cấu trúc dự án
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
Cascade nhiều tầng

Một cái reference kiểu @button.cta sẽ resolve từ thư mục shared/ của trang, rồi lội lên shared/ của thư mục cha, sau đó mới đến các token của trang. Template chỉ ghi đè đúng thứ nó cần và kế thừa mọi thứ còn lại.

Nhẹ nhàng mặc định

Thiết kế được resolve ngay trên server; browser chỉ việc nhận chuỗi class đã đóng gói. CSS thiết yếu nhất (critical) sẽ chốt đơn ngay first paint, phần còn lại load sau — đảm bảo máy yếu không phải nai lưng ra chịu tải lúc render.

HAI FILE CSS CỦA BẠN · HAI THỜI ĐIỂM LOAD
konde-server.css
critical · first paint

Được app import vào để các biến thiết kế và các bản override chống chớp giao diện (FOUC) có mặt ngay từ lần paint đầu tiên — trước khi màn hình kịp nhấp nháy.

/* konde-server.css */
:root { --kdf-primary: #1F8F47; }
[data-kdf="hero.slider"] { display: none; }
konde.css
non-critical · sau app css

Load sau CSS của framework và app, dùng cho mấy trò tweak, test thử và các ca khó nhằn — tinh chỉnh thoải mái mà không bao giờ chặn quá trình paint.

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

→ KDF chỉ tạo cả hai file này đúng một lần và không bao giờ ghi đè. Plugin sẽ ném đường dẫn thông qua biến môi trường (env) - app của bạn tự import nhé; không có trò tự động tiêm mã lén lút đâu.

06 — Đa template

Đổi giao diện
dễ như đổi ngôn ngữ.

Cách i18n đổi ngôn ngữ sao thì KDF đổi template thiết kế y chang vậy. Vẫn app đó, chung component đó, xài cùng bộ code — chỉ cần trỏ KDF_DIR qua thư mục thiết kế khác là cái UI lột xác liền.

designs/ — hai template, một app
designs/
  lander/
    shared/
    homepage.json
  newlander/
    shared/
    homepage.json
// next.config.ts
withKDF({ dir: "./designs/lander" })(nextConfig);
$layout Đảo vị trí hay giấu luôn section đi mà chả cần rớ tới một dòng code component nào.
@button Sửa toàn bộ CTA cùng một lúc thông qua cái token dùng chung.
KDF_DIR Đổi nguyên cả bộ template thiết kế, mọi thứ do host chủ động kiểm soát.
07 — Runtime API

Resolve trên server.
Ném string xuống dưới.

KDF core đọc thẳng JSON từ ổ đĩa nên nó chạy bên server-side ráo: Next.js Server Components, Astro render, Hono handler. Cứ resolve class ở đó, xong xuôi thì quăng string thuần xuống cho client component xài.

server component
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")

→ chuỗi className đã resolve

d.css("hero.title")

→ object CSS custom-properties

cn · cx · dedupeClasses

Nối class theo điều kiện, vứt các giá trị falsy, và dedupe class — mặc định không quan tâm ngữ nghĩa.

cache: auto · always · none

Lên production thì luôn cache; còn lúc dev thì nó revalidate dựa vào thời gian (mtime) & dung lượng file.

08 — Tương thích từ thiết kế

Nằm gọn bên trên
stack của bạn.

STYLING — CHỈ LƯU TÊN CLASS, KHÔNG LƯU CSS

TailwindshadcnBootstrapChakraCSS ModulesPlain CSSYour own system

KDF đâu phải CSS engine. Token chỉ chứa chuỗi class, hệ thống styling của bạn xài thế nào thì tùy. Nếu framework của bạn có vụ scan source file, cứ mạnh dạn trỏ nó tới luôn mấy file JSON: @source "../kdf/**/*.json".

RUNTIME — SERVER-SIDE JAVASCRIPT

Next.js đã test · plugin
Astro đã test
Hono đã test
Bắt đầu

Cài một lần.
Init tự lo nốt phần còn lại.

Lúc chạy lệnh cài đặt, tool sẽ sinh luôn thư mục kdf/ mẫu nếu nó chưa có. Nếu file đã tồn tại thì cứ yên tâm là không bao giờ bị đè lên.

$npm install @kondeio/kdf
$pnpm add @kondeio/kdf
$bun add @kondeio/kdf
$npm exec -- kdf init # tự scaffold bằng tay
next.config.ts
import withKDF from "@kondeio/kdf/plugin";

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