快速开始
从初始化到在群里发出第一张 React 模板截图
快速开始
本页帮你在 Karin 插件项目中接入 @karinjs/template-react,用 React 组件写一个截图模板,并在群里发出第一张图片。每一步都明确了成功标志,如果没看到预期结果就停下来检查。
前置条件:Node.js 22+、pnpm、一个基于 Karin 官方 TypeScript 插件模板的项目。
第 1 步:初始化项目
在你的 Karin 插件项目根目录执行:
npx @karinjs/template-react init命令会启动交互式向导,询问四个配置项:
- 样式方案:选择默认选项即可继承 HeroUI 主题,
bg-surface、text-accent等语义类开箱可用 - 是否生成示例模板:建议选"是",会复制官方 7 个示例(问候卡片、成员榜单、宽屏仪表盘等)到
ktr/template/,照着改就能上手 - 是否生成
src/utils/render.ts:建议选"是",这是模板渲染接入 Karin 截图的胶水层(第 4 步会用到) - 开发面板端口:保持默认或自定义端口
向导完成后,按提示安装依赖:
pnpm install✓ 成功标志:
- 项目根目录出现
karin.template.ts配置文件 - 出现
ktr/template/目录(包含示例模板,如果选择了生成) - 出现
src/utils/render.ts文件(如果选择了生成) tsconfig.json中添加了"jsx": "react-jsx"配置package.json中添加了依赖和template脚本
npx @karinjs/template-react create <项目名> 从零创建,之后走同样的问答流程。依赖管理注意事项:所有在模板中用到的依赖都需要放在 packages.json 的 devDependencies 中,构建时会整体打包(包括 React
和本包运行时),生产环境即可不用安装有关前端的相关依赖;只有 node-karin 保持排除在外。不要手动修改依赖配置——组件和渲染器必须使用同一份
React 实例,否则 hooks 会直接报错。
遇到问题? 如果初始化失败或出现错误,查看 故障排查 页面的常见问题解决方案。
第 2 步:理解模板结构
让我们看一个完整的模板示例,理解它是如何工作的。以 ktr/template/hello/card/index.tsx 为例:
import { , } from '@heroui/react'
import { , , } from 'lucide-react'
import { , type } from '@karinjs/template-react'
/** Hello 卡片模板的数据结构,适合固定宽度的信息摘要截图。 */
type = {
/** 主标题。 */
: string
/** 可选副标题。 */
?: string
/** 展示在卡片内容区的键值对。 */
: <{ : string; : string }>
}
const = ({ data }: <>) => ( < ="w-155 gap-0 overflow-hidden rounded-3xl border border-border bg-background p-0 text-foreground">
<. ="flex-row items-start justify-between gap-4 border-b border-border px-8 py-7">
< ="min-w-0">
< ="mb-3 flex items-center gap-2 text-sm font-medium text-accent">
< ={16} />
Karin 模板示例
</>
<. ="text-3xl font-bold tracking-normal">{.}</.>
{. && <. ="mt-2 text-sm text-accent">{.}</.>}
</>
< ="bg-accent text-accent-foreground" ="md" ="tertiary">
< ={14} />
HeroUI
</>
</.>
<. ="grid gap-3 px-8 py-7">
{..((, ) => (
< ={.} ="flex items-center justify-between gap-4 rounded-lg border border-border bg-surface px-4 py-3">
< ="flex min-w-0 items-center gap-3">
< ="grid size-8 shrink-0 place-items-center rounded-md bg-accent-soft text-accent">
{ === 0 ? < ={16} /> : < ={16} />}
</>
< ="truncate text-sm text-muted">{.}</>
</>
< ="text-base">{.}</>
</>
))}
</.>
</>
)
export default ({
: '问候卡片',
: 'HeroUI + lucide-react 截图卡片',
:
})关键要点:
- 路径即路由:
ktr/template/<板块>/<模板>/index.tsx自动注册为路由hello/card;直接写.tsx文件(不在目录结构中)不会被注册 - 使用语义化样式类:使用
bg-background、text-muted等语义类,主题切换和明暗模式自动适配;避免写死颜色如bg-white - 类型安全:
TemplateProps<HelloCardData>确保组件接收的数据结构类型安全 - JSON 示例数据:放在
data/子目录(如ktr/template/hello/card/data/default.json),放在模板根目录不会被识别
示例数据结构 ktr/template/hello/card/data/default.json:
{
"title": "Karin Template React",
"subtitle": "React + Tailwind CSS + TypeScript",
"items": [
{
"label": "渲染方式",
"value": "SSR HTML"
},
{
"label": "预览",
"value": "Iframe 沙盒"
},
{
"label": "类型",
"value": "注册表驱动"
}
]
}完整的目录约定和更多示例见 目录约定。
提示:语义类如 bg-surface、text-accent、border-border 等会根据用户配置的主题自动适配颜色,无需手动处理明暗模式。
第 3 步:启动开发面板
在项目根目录执行:
pnpm template这个命令等价于 ktr sync && ktr dev:
sync:扫描ktr/template/目录生成.ktr/注册表和类型定义dev:启动开发面板服务器并打开浏览器
✓ 成功标志:
- 浏览器自动打开开发面板(通常是
http://localhost:5180/__ktr/panel/) - 左侧列表显示所有可用模板(如"问候卡片")
- 点击模板名称后右侧显示实时预览
- 修改组件代码或
data/*.json保存后,预览会在 1-2 秒内自动刷新
ktr dev 会自动切换到其他可用端口,并在终端显示占用进程的详细信息。遇到问题? 如果面板无法启动或预览不显示,检查: - 是否执行了 pnpm install - .ktr/ 目录是否存在(如果不存在,手动执行 npx ktr sync) - 浏览器控制台是否有报错 更多帮助见 故障排查。
第 4 步:接入 Karin,发出第一张图
现在让我们把模板接入 Karin,在群里发出第一张图片。
4.1 渲染工具函数
如果你在第 1 步选择生成了 src/utils/render.ts,文件已经存在。让我们看看它的完整实现:
import from 'node:path'
import { , , segment, type ImageElement } from 'node-karin'
import { , type , type } from '@karinjs/template-react'
// ktr 侧按约定装配(包根定位、配置解析、注册表加载、CSS 定位、捕获目录);
// outputDir 是 karin 领域的位置,由插件显式指定。
const = (import.meta., {
: { : .(, 'karin-plugin-example') }
})
/** 注册表类型:.ktr/registry-types.d.ts 模块增强生效后为逐路由精确类型。 */
type =
/**
* 渲染模板并交给 Karin Puppeteer 截图。
* @param templatePath 模板路由,如 hello/card。
* @param data 模板数据,类型由模板组件推导。
* @param options 透传给 render.render 的额外截图参数。
* @returns 可直接 reply 的图片消息元素。
*/
export const = async < extends keyof & string>(
: ,
: <[]>,
?: <string, unknown>
): <ImageElement[]> => {
const { , , } = await (, )
if (!) {
throw new (`模板渲染失败 ${}:${}`)
}
const = await .({
: `karin-plugin-example/${}`,
: ,
: '#container',
: 'png',
: true,
...
})
const = .() ? : []
return .(() => segment.(`base64://${}`))
}关键点:
createTemplateRenderer创建渲染器实例,负责将 React 组件渲染为 HTMLrenderImage函数的data参数类型会根据templatePath自动推导,确保类型安全- 渲染完成后调用 Karin 的
render.render()进行截图 - 返回的
ImageElement[]可以直接传给event.reply()
4.2 创建测试指令
创建一个新的指令文件来测试模板渲染:
import { } from 'node-karin'
import { } from '../utils/render'
/** 触发指令:#测试模板 */
export const = .('^(#)?测试模板$', async () => {
// renderImage 的第二个参数 data 类型会根据 'hello/card' 自动推导
const = await renderImage('hello/card', { : '来自机器人的卡片',
: [
{ : '状态', : '渲染成功 ✓' },
{ : '时间', : new ().('zh-CN') }
]
})
await .()
return true
})类型安全演示:
// ✓ 正确:类型匹配
await ('hello/card', {
: '标题',
: [{ : '键', : '值' }]
})
// ✗ 错误:缺少必需字段 title
await ('hello/card', { : [{ : '键', : '值' }]
})
// ✗ 错误:title 类型错误(应该是 string)
await ('hello/card', {
title: 123, : [{ : '键', : '值' }]
})4.3 测试渲染
- 启动 Karin 开发服务器:
pnpm dev- 在群聊或私聊中发送指令:
#测试模板✓ 成功标志:
- 机器人回复一张卡片图片,显示"来自机器人的卡片"标题和状态信息
- 开发面板的数据列表中自动出现
captured.json(记录了本次真实渲染的数据) - 可以在开发面板中选中
captured.json查看捕获的数据结构
数据捕获功能:每次通过 renderImage 渲染模板时,传入的数据会自动保存到 ktr/template/<模板路径>/data/captured.json,方便你在开发面板中重现真实场景。
第 5 步:生产构建与发布
开发完成后,需要把插件打包成纯 JS 产物以便发布。产物目录由你的打包配置决定(karin 插件惯例是 lib/,本文示例都用它)。
如果宿主应用只是普通的 JavaScript Node 程序,不希望维护 Vite 或 tsdown 入口,可以改用 ktr build,直接生成可被 Node 导入的独立运行包。
执行构建命令:
pnpm build或者如果你使用的是 Vite:
vite build构建原理:
构建成功的前提是 vite.config.ts 中配置了 ktrBuildPlugin()(来自 @karinjs/template-react/plugin)。这个插件会:
- 打包前自动执行
ktr sync刷新注册表和类型定义 - 打包后将所有 CSS 编译到
<产物目录>/style.css(跟随打包器 outDir) - 由打包器生成
template-registry.js,供生产渲染器发现模板组件
✓ 成功标志:
- 产物目录(如
lib/)包含以下文件:apps/*.js(你的指令文件)utils/render.js(渲染工具)template-registry.js(模板注册表)style.css(编译后的样式)
- 发布后用户只需安装你的插件包,无需
ktr/template/源码目录
mock-registry.js 不是普通生产渲染的必需产物。只有插件代码明确调用 loadMockRegistry()、希望在生产环境读取示例数据时才把它加入打包入口。
配置示例 vite.config.ts:
import { } from 'vite'
import { } from '@karinjs/template-react/plugin'
export default ({
: [()]
})完整的构建配置和发布流程见 构建发布。
打包优化:所有依赖(包括 React)都会打包进产物,用户安装后无需额外安装依赖。生产环境只需要 node-karin 作为外部依赖。
下一步
恭喜!你已经完成了从初始化到发出第一张图的完整流程。现在你可以:
编写模板
深入了解 defineTemplate 字段、ctx 上下文、外观规则
mock 数据
学习 TS mock、JSON mock、captured.json 数据捕获
接入 Karin
renderImage 逐段讲解与更多指令示例
开发建议: - 在开发面板中调试模板样式和数据结构,确认无误后再接入 Karin 指令 - 使用 captured.json 收集真实场景的数据,作为测试用例 -
遵循语义化样式类约定,确保主题切换正常工作