BTST Shadcn Registry
插件 UI 页面以 shadcn v4 registry 的形式分发,因此使用者可以通过 npx shadcn@latest add 弹出并自定义 UI 层。
关键文件
| 文件 | 用途 |
|---|---|
| packages/stack/scripts/build-registry.ts | 构建脚本——用 glob 匹配插件组件、重写导入、输出 JSON |
| packages/stack/scripts/test-registry.sh | 端到端测试——打包 @btst/stack,通过 shadcn 安装,构建 Next.js 项目 |
| packages/stack/registry/btst-{name}.json | 按插件生成的注册表条目(已提交,由构建脚本重新生成) |
| packages/stack/registry/registry.json | 合并后的注册表集合(已提交,重新生成) |
| .github/workflows/registry.yml | CI——在 PR 和 main 上重新构建注册表并运行端到端测试 |
设计规则
- Hooks 被排除——组件从 @btst/stack/plugins/{name}/client/hooks 导入 hooks。只有视图层可弹出。
- 可路由页面——当插件支持页面覆盖时,通过客户端插件配置上的 pageComponents 回接。
- @workspace/ui 导入会被重写:标准 shadcn 组件 → registryDependencies;自定义组件(page-wrapper、empty 等)→ 作为 registry:component 文件从 packages/ui/src/ 嵌入。
- 保留目录结构——源文件落在 src/components/btst/{name}/client/{relative},因此所有相对导入仍然有效。
- 工作区组件 API 兼容性——工作区版本必须与标准 shadcn API 匹配。绝不要添加标准 shadcn 没有的自定义 props。
EXTERNAL_REGISTRY_COMPONENTS
多文件的 @workspace/ui 组件(目录而非单文件)必须映射到外部注册表 URL:
// In packages/stack/scripts/build-registry.ts
const EXTERNAL_REGISTRY_COMPONENTS: Record<string, string> = {
"auto-form": "https://shadcn-registry.example.com/auto-form",
"minimal-tiptap": "https://shadcn-registry.example.com/minimal-tiptap",
// add new multi-file components here
}
如果新组件从 @workspace/ui/components/my-dir/...(一个目录)导入,请在此处添加它。
新增插件——4 个步骤
- 在 packages/stack/scripts/build-registry.ts 的 PLUGINS 中添加一个 PluginConfig 条目
- 运行 pnpm --filter @btst/stack build-registry
- 在本地运行 pnpm --filter @btst/stack test-registry
- 提交更新后的 registry/*.json 文件
注意事项
- 插件变更后未重新构建注册表——始终运行 build-registry 并提交更新后的 JSON。CI 会拒绝过时的输出;在最终验证前提交它。检查后不要自动提交或使用跳过 CI 的提交。
- 找不到 @workspace/ui 子路径组件——如果新组件从目录导入,请将其添加到 EXTERNAL_REGISTRY_COMPONENTS。
- Hooks 被意外包含——检查 hooks/ 文件在构建输出中是否显示为 skip。如果某个插件的 hooks 位于非标准位置,请更新 build-registry.ts 中的 shouldExclude()。
- 工作区组件上的自定义 prop——移除自定义 prop,改用标准 shadcn API。当安装共享同一依赖(例如 popover)的其他组件时,shadcn CLI 会覆盖嵌入的组件。