平台无关的设计系统内核:seed → 一棵树 → 快照。Web 的 CSS 只是它的一个出口。
@ultime/core 把少量可编辑的设计输入(seed)算成一棵 DTCG 形态的 token 树,再翻译成 CSS / JSON / DTCG。
它不含组件、class、路由或配置界面,也不承载品牌:同一套机制可以生成不同风格。
| 是 | 不是 |
|---|---|
| 一份可复现的样式数据源 | 组件库 / 样式框架 |
| seed 驱动的派生引擎与出口 | 设计工具;配置器建立在 @ultime/core/studio 之上 |
| 中性工具:只给档与生成参数 | 语义表、布局、断点、目标尺寸(归上层) |
| 可入库、可 diff、可交换的快照 | 组件状态、交互行为或业务规则 |
pnpm add @ultime/coreNode.js >= 22.18。内核的 . / ./exporters / ./tools / ./seed 出口是编译后的 JS,零第三方依赖;
./studio 出口(配置器)依赖 @ultime/studio,ultime-core bin 依赖 @ultime/cli;不用配置器 / CLI 时不会进入你的产物。
所有出口 ESM-only:用 import / import() 消费,不提供 require 入口;类型来自 dist/*.d.ts,包体不含 src/。
import { buildCore } from '@ultime/core'
import { treeToCss, treeToJson, treeToDtcg } from '@ultime/core/exporters'
const result = buildCore({ color: { chromaRatio: 0.9, primaryHue: 250 } })
result.tree // 一棵树
result.contracts // 合同:rows / total / failed / ids
result.counts // token 计数
const css = treeToCss(result)换品牌 / 调档只改 seed,然后重跑构建;不要手改快照。
光影用同一份引擎求解;静态快照只表达默认形态 convex:
import { solveLight } from '@ultime/core'
solveLight({ form: 'concave', depth: 3, mode: 'dark' })solveLight 只收形态 / 深度 / 模式,不收尺寸、圆角或组件名;flat / convex / concave 在构建期取,不写入静态快照。
同一次导出只派生一次。CLI、studio 与脚本都走 resolveThemeConfig / exportTheme:
import { exportTheme, resolveThemeConfig } from '@ultime/core/tools'
const { config, diagnostics } = resolveThemeConfig({ tokens: { output: 'styles' } }, { seed })
const { build, artifacts } = exportTheme(config)
build.core // CoreResult
build.manifest // kernel.json 的内容
build.artifacts // 产物清单(path / content / bytes)
build.diagnostics // error / warn / infoplanProject 是内部引擎执行器;需要更低层控制时可直接调用,但不要另拼产物清单。
选择与派生是导出配置,可选;默认导出与定制导出走同一条路径。@ultime/core/tools 提供统一管线:
import { exportTheme, resolveThemeConfig } from '@ultime/core/tools'
const { config, diagnostics } = resolveThemeConfig({
tokens: { output: 'styles' },
selection: { categories: ['skeleton', 'color'], steps: { space: [1, 2, 4, 6], radius: [1, 3, 5] } },
derivation: { light: { form: 'flat' } },
})
const result = exportTheme(config)
result.build // ProjectBuild:core / manifest / artifacts / diagnostics
result.artifacts // 定制产物:tokens.css / tokens.json / tokens.dtcg.json(不含 kernel.json)
result.diagnostics // 未知类别 / 档位、缺失档位、空选择、semantics 提示
result.selected // 配置了 selection / derivation 时才存在需要更细的控制时,selectBuild / selectTree / deriveTree 仍可从 @ultime/core/tools(或 /studio re-export)调用。
- 类别:
skeleton/color/light/motion;省略 = 全部,空数组 = 不启用。 - 档位:
space/size/radius/fontSize/lineHeight/letterSpacing/shadow/occlusion/motionDuration/motionDelay/motionLoop;省略 = 该组全量,空数组 = 去掉该组数字档位。 - 非档位 token(
shadow.color/font/motion.easing等)跟随所属类别保留。 - 自定义派生只调用 core 引擎函数:目前支持
light.form的flat/convex/concave,按solveLight重算highlight/shade,不写回 seed,也不支持用户 recipe。 kernel.json描述完整内核,不属于定制产物;semantics.json也不在定制导出里生成。selection/derivation可选地写在配置根上,CLI 与 studio 都能读;省略 = 全量 / 静态默认。
为什么是一棵树、为什么派生优先、数值出处怎么定:设计取舍见 DESIGN.md,本节只写机制。
seed(少量可编辑输入)
│
▼
buildCore:schema + derive + check
│
▼
树(DTCG 形态:token / group / 模式值)
│
├── CSS 变量
├── 原生 JSON
└── DTCG 交换格式 + manifest
- seed 是唯一输入:色相 / 彩度 / 中性配方 / 画布对称 / 面目标 / 前景端点 / 启用模式 / 圆角基座 / 字号基准 / 字体栈 / 光源方向与光色 / 受光边 alpha / 动效步长。
- 树只有两种节点:
token($type/$value)与group;组只做分隔,不承载语义。 - 类别不是包:
skeleton/color/light/motion是同一棵树里的类别,可按类别整块裁剪。 - 光影五槽:
highlight.key/highlight.ambient/shade.key/shadow/occlusion;静态 tokens 只表达convex,flat/concave走solveLight。 - 模式是作用域:颜色与
highlight.key/shade.key的值是{ light, dark };写进 CSS 时变成值位 + 无后缀开关。 - 语义不在树里:
gap.*/type.*/border.*只写路径,归可选的语义表。 - 实心面前景独立:每个色族有
tone.{族}.solid.foreground;ink只用于中性面,彩色实心面必须用foreground。
import '@ultime/core/tokens.css'padding: var(--space-6);
font-size: var(--fs-4);
line-height: var(--lh-3);
border-radius: var(--radius-5);
background: var(--color-surface-raised);
color: var(--color-ink-primary);
border-color: var(--color-line-2);
box-shadow: var(--shadow-2);
transition: opacity var(--motion-duration-2) var(--motion-easing-standard);
/* 实心填充:文字必须用该族的 foreground */
background: var(--color-tone-primary-solid-fill-rest);
color: var(--color-tone-primary-solid-foreground);深色由作用域解析:
<html data-theme="dark">- 颜色读无后缀开关;
-light/-dark是值位,只有主题切换本身才直接读。 - 长度类是
rem,字距是em,光影是px,行高无单位。 prefers-reduced-motion: reduce下时长与延迟归零,循环不归零;循环由组件显式停。
| 入口 | 提供 |
|---|---|
@ultime/core |
buildCore / buildManifest / solveLight / planGradient / 树工具 / 合同 / 版本 |
@ultime/core/exporters |
treeToCss / treeToJson / treeToDtcg;只读树 |
@ultime/core/tools |
统一管线 resolveThemeConfig / exportTheme / exportThemeArtifacts;构建计划 planProject;选择 / 派生 selectBuild / selectTree / deriveTree;默认值;配置校验;语义表模板 |
@ultime/core/studio |
无头配置器定义:字段 / 预设 / 校验映射 / 预览 / 导出;选择 / 派生 API 由 tools 提供并 re-export;渐变判断:planGradient |
@ultime/core/seed |
seed 类型 / 默认值 / 深合并 / JSONC / 指纹 |
planGradient(from, to, { length, bitDepth }) 只做判断:建议插值空间、是否需要中间色标、阶梯纹风险、对比度采样点;经验阈值集中在 GRADIENT_RULES,可整体覆盖。它不产 token、不拼 CSS。
产物编排(选出口、定目录、排序)走工具层,不写盘:
import { exportTokens } from '@ultime/core/tools'
const files = exportTokens({
seed: { color: { primaryHue: 250 } },
platforms: ['css', 'json'],
output: 'src/styles/tokens',
})按类别裁剪 CSS:
treeToCss(result, { include: ['color', 'motion'] })ultime-core 由本包提供(bin/ultime.js);参数 / help / 退出码设施来自 @ultime/cli,命令与规则都在 core。
ultime-core init # 写一份 ultime.config.json
ultime-core build # 读配置 + seed → tokens.* / kernel.json
ultime-core build --check # 只比对,不写盘
ultime-core inspect # 只读检查:产物 / 平台 / 类别 / 合同 / 颜色 / 诊断
ultime-core schema --json # seed 字段 / 出口 / 语义表配置模型为 tokens.seed / platforms / output / semantics,可选 selection / derivation。
semantics 是可选产物:只有配置了才生成 semantics.json,它不进树,也不进 kernel.json。
CLI、库 API 与 core/studio 都走 tools/pipeline:默认配置与自定义配置同一条出口。
仓库内开发也可用 pnpm ultime(等价于 vpx src/cli/index.ts)。
| 文件 | 性质 | 说明 |
|---|---|---|
tokens.css |
生成物 | 全量原料:几何 / 排版 / 颜色 / 光影 / 动效;含 reduce 覆盖 |
tokens.json |
生成物 | 树形快照,值与 CSS 同源;模式值输出 { light, dark } |
tokens.dtcg.json |
生成物 | DTCG 2025.10 交换格式;真正嵌套 group,模式值是 light / dark 两个 token |
kernel.json |
生成物 | manifest:schema / engine 版本、seed 与指纹、计数、合同摘要、颜色报告 |
dist/*.js |
构建物 | 库出口:. / ./exporters / ./tools / ./studio / ./seed |
产物随仓库入库,用于 diff 与离线消费;禁止手改,改 seed 后重跑构建。
pre-commit会重算产物并逐字节比对,拦下「新源码带旧产物」的提交。dist/*.js默认压缩;注释与设计说明留在源码、本 README 与DESIGN.md,不随产物发布。dist/*.d.ts不压缩。
packages/core/
├── bin/ultime.js CLI 薄入口(ultime-core → dist/cli.js)
├── src/
│ ├── cli/ 命令:init / build / inspect / schema + 配置读写
│ ├── seed.ts seed 类型 / 默认值 / 深合并 / JSONC / 指纹
│ ├── tree.ts token / group / 模式值 / 遍历 / 合成
│ ├── build.ts seed → 派生 → 一棵树 → 合同 → manifest
│ ├── contracts.ts 几何 / 动效 / 树结构 / 颜色报告
│ ├── version.ts schemaVersion / engineVersion
│ ├── model/
│ │ ├── skeleton.ts space / size / radius / fs / lh / ls / font
│ │ ├── color/ 颜色数学 + 中性灰 + 画布 / 面阶 / 墨 / 线 / 色族矩阵
│ │ ├── light.ts shadow / occlusion / highlight / shade
│ │ └── motion.ts duration / loop / delay / easing
│ ├── exporters/ CSS / JSON / DTCG(只读树)
│ ├── studio/ 配置器定义:字段 / 预设 / 校验映射 / 预览 / 导出编排
│ └── tools/ 统一管线 / 构建计划 / 选择与派生 / 项目配置 / 语义表模板
├── scripts/
│ ├── build.ts 唯一构建入口(`--check` 只校验)
│ └── check-model.ts 内核守卫(零依赖 / 方向 / 类别隔离 / 无载体语法)
├── tests/ 回归基线
├── theme.example.json 示例 seed(可改输入)
└── tokens.* / kernel.json ⚠️ 生成物
- seed 是唯一输入:换品牌 / 调档只改 seed,然后重跑构建。
- 模型不带载体:树里只存值、量纲与
$type;px/rem/var()/color-mix的写法在出口。 - 语义不在树里:角色(enter / exit / press)、语义表(gap / type / border)、布局(容器 / 栅格 / 断点)、 目标尺寸(44 / 28–32)归上层;官方语义表模板属工具层,不参与树的计数与合同。
- 方向靠守卫:
model不 importbuild/exporters/tools/studio,四个类别之间也互不 import;scripts/check-model.ts机械拦截。 - 可复现:同 seed 同版本逐字节相同;manifest 不含时间戳与绝对路径。
新增内容前先问:它是值还是用法?依赖平台吗?能由参数派生吗?能机检吗?会不会出现第二份正文?
- 包版本按 semver;
kernel.json里的schemaVersion描述树与合同字段的兼容面,engineVersion描述派生实现。 - 依赖基线:
@ultime/studio/@ultime/cli发版后,core 下次发版前更新 lockfile 到最新已发布版本并重建测试;已发布版本不追改。 - 0.9.1 发布产物默认压缩;API、树与合同不变。
- 0.9.0 新增
planGradient(根出口与./studio):树、合同与产物不变,engineVersion不变。 - 0.7.0 新增
@ultime/core/studio选择 API;树、合同与派生值不变,快照只有engineVersion变化。 - 0.5.0 是契约刷新:
rim→highlight.ambient,bevel.highlight/shade→highlight.key/shade.key;seed 的lightTint/ambientTint/rimAlpha/bevel改为lightColor/ambientColor/ambientAlpha/key。不提供迁移器。 - 下游优先读
kernel.json与公开出口,不依赖src/内部结构。 - 0.x 阶段导出面仍可能调整;升级前对比两份
kernel.json(版本 / 计数 / 合同摘要)即可看出差异。
pnpm install
pnpm build # 产物 + dist 库出口(含 bin)
pnpm ultime # 开发态 CLI(vpx src/cli/index.ts)
pnpm build:tokens # 只生成 token / manifest
pnpm test # Vitest 回归
pnpm check # 格式 / lint / 类型 / 守卫 / 产物同源指定项目 seed:
pnpm build:tokens -- --seed path/to/theme.json改了 theme.example.json 或 src/model/** 之后必须重跑 build:tokens;check 会拦下产物与源不一致的构建。
- 机器入口是
kernel.json与ultime-core schema --json;不要让 agent 从 Markdown 里抄数值。 - 完整设计规范(取值理由、对比度与配对判据)不随包分发:安装
@ultime/designcraftskill(npx skills add ultime-space/skills --skill designcraft)阅读。 - 包内 AI 入口是
llms.txt(路由)与SKILLS.md(能力表);AGENTS.md/rules/只在仓库内维护。
MIT,见 LICENSE。