Konde Design Framework

i18n 搞定多语言,
KDF 搞定你的设计。
全都装进 JSON 里。

为服务端 Web 应用和 AI 辅助开发量身定制的 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 文件系统
依赖项
零运行时依赖
已测试框架
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 智能体会自己在那边瞎猜颜色、间距、排版和布局。
  • 每次你都得在聊天框里教它怎么改,改完还是不对。
  • 一有变动,你就得去各个组件文件里到处翻。
  • 稍微多聊几句,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
源文件只改一次,再也不用每次开新对话都在聊天框里口水连篇地描述怎么调 UI 了。
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 · 纯 CSS · 你自己写的样式系统 —— KDF 没想干掉它们任何一个。
04 — 语法词汇

六个符号,
一套语法。

KDF 里存了 class 类名、共享引用、区块顺序,还有 CSS 变量。但它绝对不会去碰你的业务逻辑、事件监听、数据请求、权限控制或者无障碍 (a11y) 功能。

data-kdf
映射关系

每个用上 token 的元素都会带上一串对应的路径。DOM 节点直接就能追溯回 JSON —— 这对自动化扫描、写测试或者让 AI 来审查简直爽翻了。

data-kdf="hero.title"
d(path)
访问器

把路径解析成 className 字符串。d.css() 会直接给你扔回来一个 CSS custom properties 对象。

className={d("hero.title")}
@
共享引用

指向 shared/ 目录下的高频复用 token。Refs 还能链式调用,或者加上额外的 class 来做扩展。

"@button.cta" shadow-xl
$layout
顺序与可见性

其实就是一个存着区块 keys 的数组。列出来的区块按顺序渲染;没列出来的,宿主应用会自动把它们藏起来。

["hero", "features", "footer"]
$
组件标识

主要是给 AI 智能体和宿主工具看的元数据 —— 告诉你这个 token 是被哪个组件渲染的,还顺带附上了变体和尺寸提示。

"$": "Button"
css
自定义属性

遇到那些没法用 class 表达的值,直接通过 d.css() 以行内样式变量的形式扔进去。

{ "--kdf-accent": "#4F46E5" }
05 — 架构设计

共享默认值,
页面按需覆盖。

设计 token 存在两个地方:可以随便复用的默认值放在 shared/ 里;而页面级别的配置只覆盖它确实需要改的那点东西。最后生成两个由你完全掌控的 CSS 文件,一个保首屏,一个用来兜底。

项目结构
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)

@button.cta 这样的引用,解析的时候会先看页面的 shared/,再看父级的 shared/,最后看页面的 tokens。模板只覆盖自己要改的,剩下的原样继承过来。

主打一个轻量

设计都在服务端解析完了;浏览器拿到的全是干干净净的 class 字符串。关键 CSS 跟着首屏一起加载,剩下的慢慢来 —— 绝不给低配机器增加渲染负担。

两个完全归你管的 CSS 文件 · 两个加载时机
konde-server.css
关键样式 · 首屏渲染

应用加载时直接 import 进来,让设计变量和防闪烁 (no-FOUC) 的覆盖样式在第一帧就准备好 —— 页面绝对不会闪一下。

/* konde-server.css */
:root { --kdf-primary: #1F8F47; }
[data-kdf="hero.slider"] { display: none; }
konde.css
非关键样式 · 晚于应用 CSS

等框架和应用的 CSS 都加载完了再加载它,主要用来做微调、搞点实验性样式或者做个兜底 —— 这种细枝末节的东西,犯不上阻塞页面渲染。

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

→ KDF 只会把它们建好一次,以后绝对不碰。插件会通过环境变量把路径暴露给你,你自己决定在应用里怎么 import;背地里绝对不搞什么偷偷注入那一套。

06 — 多套模板

换个设计模板,
就像换语言包一样简单。

就像 i18n 切换语言一样,KDF 切换设计模板也是丝般顺滑。应用没变,组件没变,连代码都不用动 —— 把 KDF_DIR 指向另一个设计文件夹,整个站点的脸直接就换了。

designs/ — 两套模板,跑在同一个应用上
designs/
  lander/
    shared/
    homepage.json
  newlander/
    shared/
    homepage.json
// next.config.ts
withKDF({ dir: "./designs/lander" })(nextConfig);
$layout 不动任何组件代码,就能重新排版或者隐藏页面区块。
@button 改一个共享 token,全站的 CTA 按钮瞬间一起换装。
KDF_DIR 直接把整套设计模板换掉,这就是宿主系统该干的活。
07 — 运行时 API

在服务端解析好,
纯字符串往下传。

KDF 核心直接从硬盘里把 JSON 读出来,所以它理所当然地跑在服务端:不管你是 Next.js Server Components, Astro 渲染器, 还是 Hono 处理器。在服务端把 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 custom-properties 对象

cn · cx · dedupeClasses

把条件 class 拼起来,扔掉 falsy 的空值,顺便去个重 —— 默认没有任何语义负担。

缓存控制: auto · always · none

上生产环境自动给你加缓存;本地开发的时候就看文件的修改时间 (mtime) 和大小来热更新。

08 — 极致兼容

它可以无缝坐在
你的整个技术栈上面。

样式层 —— 只存 CLASS 名,绝不硬塞 CSS

TailwindshadcnBootstrapChakraCSS ModulesPlain CSSYour own system

KDF 并不是个 CSS 引擎。只要你的样式系统认,Token 里存什么样奇葩的 class 字符串都行。要是你的框架有扫描源码文件这步操作,顺手把 JSON 的路径也给加上呗:@source "../kdf/**/*.json"

运行时环境 —— 服务端 JAVASCRIPT

Next.js 测过了 · 插件已就绪
Astro 测过了
Hono 测过了
快速上手

一键装好,
剩下的交给我们。

要是没有 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);