空间内嵌应用:应用模板

Knodo 应用模板机制:把工作空间的「形态」沉淀为可复用的模板,AI 辅助开发,一键分发给团队

应用生态

Knodo 应用生态(App Ecosystem)让你把一个工作空间的「形态」 —— 包括侧边栏布局、自定义面板、业务视图 —— 沉淀成可复用的模板,然后一键分发给团队其他人。

比起从零搭建一个新空间,基于 App 模板创建的空间开箱即用:侧边栏已经按业务流程排好,自定义面板(比如"客户列表"、"销售漏斗")直接显示业务数据,团队成员打开即用。

核心概念

什么是 App(应用模板)

App = 工作空间的形态。它描述了:

  • 侧边栏布局:显示/隐藏哪些内置面板(任务、知识、变更等),追加哪些自定义面板
  • 面板组件:自定义面板的 UI 是什么样、放哪些数据
  • 文案重命名:把「知识」改为「代码」、把「任务」改为「跟进」之类
  • 元数据:名称、版本、图标、作者、分类

一个 App 可被多个工作空间同时绑定,每个空间独立拥有自己的数据,但 UI 形态完全一致。

App vs Plugin 的区别

Knodo 平台现有两个扩展机制,分工清晰:

维度Plugin(插件)App(应用模板)
解决什么AI 能做什么空间长什么样
组成Agent 角色、Skill 技能、命令、Hook面板、侧边栏、布局
绑定关系多对多(一个空间装多个插件)一对一(一个空间用一个 App)
运行时AI 对话期间调用打开空间就生效

两者独立运作:一个基于「销售 CRM」App 创建��空间,可以同时装 Javis 插件跟 AI 对话、装 Pagecraft 插件生成页面。

内置 App

平台预置两个 App 模板:

  • 通用(general):默认布局——知识库 + 任务 + 对话三栏,大多数场景开箱即用。老工作空间自动绑定此 App
  • 应用模板开发(app-dev):平台内 AI 辅助开发应用模板的专用模板。点击即可进入,一句话描述需求就能生成面板 → 实时预览 → 发布到应用模板库。详见应用模板开发章节

使用流程

1. 发现和使用

空间列表页右上角 → 「应用模板」按钮 打开管理弹窗。这里能看到:

  • 内置 App(如「通用」)
  • 组织内其他成员发布的 App(INTERNAL 可见性)
  • 自己发布的 App(PRIVATE 可见性)
  • 公开的 App(PUBLIC 可见性,跨组织可见)

点击任一 App 进入详情,可以看:

  • 面板定义:这个 App 有哪些自定义面板
  • 布局配置:隐藏了哪些内置面板、面板顺序
  • 原始 Manifest:完整的 app.yaml 内容

2. 基于 App 模板创建工作空间

「新建工作空间」 弹窗(AI 创建 / 从模板创建两种路径都支持),新增了 「应用模板」 区域。

  • 不选 → 默认使用「通用」
  • 选中某个 App → 新空间的侧边栏、面板会按该 App 的 manifest 渲染

APP模板

3. 为现有空间切换 App

进入空间 → 设置 → 应用模板 Tab:

  • 看到当前绑定的 App 信息
  • 「切换模板」 展开选择器
  • 确认后侧边栏立即按新 App 配置重新渲染
  • 空间内容(知识库、任务、对话记录)不受影响,只是「外壳」变了

切换APP模板

应用模板开发

为什么这么做

传统做法开发��个前端应用要:搭脚手架 → 选组件库 → 写代码 → 调样式 → 打包 → 部署。对非程序员用户,这条路基本走不通。

Knodo 的做法是把开发环境做成一个工作空间,让 AI 完成所有技术细节:

  • 知识库(= 代码目录):AI 把源码写在这里
  • AI 对话:你用自然语言提需求、改样式、加功能
  • 预览面板:浏览器端编译 + 实时预览,所见即所得
  • 一键发布:AI 自动打包上传

整个过程你只需要:想清楚要什么 + 看预览说满意还是不满意

创建开发空间

新建工作空间 → 选择 「应用模板开发」 应用模板 → 完成创建。

进入后左栏是 预览 面板,默认展开;还能看到 代码 面板(其实是知识库,专门为此模板重命名)。

创建开发空间

跟 AI 说需求

在对话里描述你要做什么,越具体越好:

/javis:app-developer 做一个电影收藏管理应用,要能新增电影(名字、年份、评分)、按年份筛选、按评分排序

AI 会:

  1. javis 插件内置了一个 app-developer 的 skill,他知道如何构建应用模板
  2. 根据需求推导 slug(例如 movies
  3. app.yaml 定义面板和布局
  4. src/panels/movies.tsx 实现 UI 逻辑;需要时再补 src/libs/***.module.css
  5. 保存文件

几秒后 预览 面板会自动编译、自动挂载你的组件。

预览模式

预览面板顶部有两个按钮,切换查看效果:

模式切换方式效果
开发默认不改变布局,面板清单里展开看每个面板的组件(内嵌预览)
预览点「预览」完全切换为你的 App 布局,对话区也会隐藏,自动打开第一个面板

预览模式

预览模式下右下角有 「返回开发」 悬浮球,双击 ESC 也能退出。即使 AI 写出了死循环代码,逃生球一样能点。点击「返回开发」后会自动回到预览面板。

预览模式

迭代优化

看到预览后,可以继续跟 AI 说:

把电影卡片的背景改成渐变色

加一个「已看过」的筛选条件

把评分数字字体放大一点

AI 会 Read → Edit 现有文件。由于 AppPreview 监听了源码变化,保存后自动重新编译刷新。

样式

默认有两档方式:

  • 基础模式:直接在 TSX 里写 className,配合 Tailwind utility class。大多数场景够用,也是兼容性最稳的方式
  • 增强模式:在当前环境已启用时,使用 *.module.css 做局部样式抽离,并可在 App 根容器上定义局部 CSS 变量

增强模式的边界:

  • 只支持 src/panels/**src/libs/** 下的 *.module.css
  • 不支持普通 .css
  • 不支持 :globalhtmlbody:root.dark
  • App 根容器变量只保证作用于当前 App 的非 Portal 子树

发布

满意后点 预览 工具栏的 「发布」 按钮。会弹出确认对话框,点击确认后:

  • 指令会自动发到对话框(你不需要手动打字)
  • AI 执行 app-developer Skill 的 pack-and-upload.sh 脚本
  • 脚本用 build-panels.mjs 编译 TSX、校验 import / CSS 规则 → 打 ZIP → 直接调 POST /api/v1/apps
  • 返回新 App ID

完成后:

  • 此 App 出现在空间列表页 「应用模板」 管理弹窗里
  • 任何成员创建工作空间时可以选择这个 App
  • 你自己可以在设置里切换任意空间到此 App

外部开发 + 手动上传

如果你有现成的应用包 ZIP(含 app.yaml + panels/*.js,必要时带 sibling panels/*.css),在 应用模板管理弹窗 → 「上传应用」 上传即可。

参考示例:apps/app-plugins/customer-management/(源码结构 + 打包脚本)。

可见性与管理

可见性管理

可见性谁能看到典型用途
私有(PRIVATE)仅创建者自用的个人工具、开发中未稳定的版本
组织内(INTERNAL)同组织成员团队内部复用的标准应用
公开(PUBLIC)所有组织平台级模板、合作伙伴开放的公共应用

上传后可在 应用模板管理 → 某个 App → 编辑信息 里修改可见性。

覆盖发布(迭代已有 App)

同一个 slug 的 App 再次发布时,系统会判断:

  • 你是原创建者 → 弹出确认对话框,提示会覆盖当前版本,所有绑定此 App 的工作空间会立即使用新版。你点「覆盖」后完成更新
  • 你不是原创建者 → 拒绝覆盖,必须修改 slug 后重新发布(或联系原作者)

⚠️ 覆盖发布会立即影响所有绑定此 App 的工作空间 —— 如果跨团队共用,建议版本号同步升级,并提前告知相关成员

使用应用模板开发空间修改后再发布时,如果是同一个 slug,AI 会先发一次请求 → 后端返回 409 冲突 → AI 问你是否覆盖。你确认后 AI 再发一次带覆盖标识的请求,成功后告诉你「已覆盖更新」。

权限保护:只有原作者能覆盖。如果你在别人的空间里发布一个同 slug 的 App,会被后端拒绝(403),需要你改 slug 重试。

删除 App

在应用模板管理 → [⋯] → 删除 后:

  • 如果当前没有空间使用此 App → 直接删除
  • 如果有空间使用此 App → 弹出确认对话框,列出受影响的空间。确认后:
    • App 被删除
    • 这些空间的 appId 自动降级为「通用」App
    • 空间内容完全保留(只是失去了自定义面板,回到默认布局)

技术规范

文件约定

AI 生成的文件结构(你能在「代码」面板里看到):

<workspace-root>/ ├── app.yaml # App Manifest(必需) ├── package.json # npm 依赖声明(可选) ├── src/ │ ├── panels/ │ │ ├── <view-key-1>.tsx # 每个 view 对应一个 TSX 文件 │ │ ├── <view-key-1>.module.css # 局部样式(仅在当前环境已启用时) │ │ └── <view-key-2>.tsx │ └── libs/ # 共享组件 / hooks / utils(可选) └── dist/ # 打包产物(脚本生成,无需手动编辑) └── <slug>.zip

严格命名约定

view key ⇄ entry 文件名 ⇄ 源码文件名 必须三者对齐

  • app.yamlviews.<key>.entry = ./panels/<key>.js(发布后的路径)
  • 源码 src/panels/<key>.tsx
  • 如果启用了 CSS Modules,构建后可能还会生成 ./panels/<key>.css 作为样式 sidecar;这是产物文件,不是源码入口
  • 已发布 App 会尝试加载同名 CSS sidecar;旧 App 没有 ./panels/<key>.css 时继续只加载 JS,不会白屏

违反约定会导致预览报"源文件不存在"。AI 会严格遵守这个约定。

app.yaml 约束

name: 客户管理 slug: crm version: 1.0.0 description: CRM 客户关系管理 category: CRM views: customers: title: 客户列表 type: component entry: ./panels/customers.js layout: sidebar: hide: [tasks, changes] # 隐藏的内置面板 rename: files: 资料 # 把"知识"重命名为"资料" panels: - key: customers title: 客户列表 icon: Users
字段说明
name必填
slug必填,小写字母 + 数字 + 连字符
version必填,x.y.z 格式
views必填,至少一个面板定义
layout.sidebar.hide可选,要隐藏的内置面板 ID 数组
layout.sidebar.rename可选,内置面板重命名映射(如 { files: 代码 }

发布后,这份 manifest + 编译好的面板资产(panels/<key>.js,必要时带 panels/<key>.css sibling CSS)会被平台注册到应用模板库,供组织内/外成员复用。运行时会尝试加载同名 CSS sidecar;旧 App 没有 CSS 文件时仍按原有 JS 面板加载。

TSX 文件约束

AI 生成的面板组件需要满足:

  • export default 导出 React 组件
  • 组件接收 { workspaceId: string } props
  • 可以 import react(Hook 都能用)
  • 可以 import 下列平台能力(详见面板可用的平台能力):
    • @knodo/api:调用平台前端行为(发对话消息等)
    • @knodo/ui:复用平台桥接组件(目前稳定开放:ChatInterface
    • 可以直接 fetch 任何 /api/v1/... 后端接口(same-origin 自动带凭证)
    • 不能 import 平台私有模块(@/components/...@/stores/... 等)
  • Tailwind 类名可用
  • 在当前环境已启用时,可以 import *.module.css 并与 className 混用
  • 普通 .css 不可用;也不要写 :globalhtmlbody:root.dark

面板可用的平台能力

除了纯 React 组件能力,面板还可以调用平台暴露的三类能力做更复杂的事。

1. @knodo/api — 调用平台前端行为

用在「面板想让 AI 帮我做事」这类场景。这些能力不是后端 API(没有 HTTP endpoint),必须走 @knodo/api

方法作用
chat.send(text)把一段文本直接作为用户消息发送到当前激活的对话 Tab,AI 立即开始回复
chat.fill(text)把文本填进输入框(不自动发送),留给用户改完再点发送

示例:

import { chat } from '@knodo/api' <button onClick={() => chat.send('帮我分析这条订单异常')}> 交给 AI 分析 </button>

2. @knodo/ui — 复用平台组件

有些组件实现极复杂,自己写不划算。平台把它们以 @knodo/ui 形式对面板开放。

当前可用说明
ChatInterface完整的 AI 对话窗口。包含消息列表、流式渲染、命令选择、文件上传、模型切换等。面板可以直接嵌入用

示例(把对话嵌进自己的面板):

import { ChatInterface } from '@knodo/ui' export default function MyPanel({ workspaceId }) { return ( <div className="flex h-full flex-col"> <header>...我的业务内容...</header> <div className="flex-1"> <ChatInterface workspaceId={workspaceId} welcomeMessage="💡 可以问我任何关于这份数据的问题" hideFileSelector /> </div> </div> ) }

@knodo/ui 会随着平台迭代逐步增加新组件(看板、Markdown 查看器等)。

3. 直接 fetch 后端 API

面板运行在 same-origin,所有 /api/v1/... 接口都能用标准 fetch 调用,凭证自动携带:

fetch(`/api/v1/workspaces/${workspaceId}/tasks`, { credentials: 'include', }).then((r) => r.json())

注意事项

  • 面板跑在平台主 React 树里,不是 iframe。基础主题 token 会在非 Portal 子树中自动继承;高级场景可在启用后使用 *.module.css 和 App 根容器 CSS 变量
  • @knodo/api@knodo/ui 的类型提示需要编辑器支持,AI 直接写就行
  • 所有能力都有版本承诺@knodo/api@knodo/ui 的破坏性变更会通过 Skill 文档和发版说明告知
  • 不要尝试绕过去 import @/...,会编译失败
  • 不要指望 App 根容器变量自动影响 DialogPopoverTooltip 等 Portal 浮层

隐藏 / 重命名内置面板

默认平台空间有 7 个内置面板:

ID默认文案说明
tasks任务任务管理
files / knowledge知识知识库文件树(两个 ID 互为别名)
changes变更Git 变更视图
views分析数据视图
automation自动化定时任务
guideline指引工作指引
chat——右侧对话区

你可以告诉 AI:「不要任务和变更面板」→ AI 会在 manifest 加 hide: [tasks, changes]。也可以重命名:「把知识改名为资料」→ AI 加 rename: { files: 资料 }。完全沉浸式应用(只留一个面板)也可以:「只保留我的面板,其他全部隐藏,包括对话区」。

隐藏面板

适用场景

适合做纯前端的业务工具:

  • 数据看板(内嵌 echarts / recharts 后可视化)
  • 清单工具(待办、笔记、收藏)
  • 表单类应用
  • 轻量 CRM / 跟进工具
  • 文档展示 / 知识库门户

目前不适合做的:

  • 需要重度 UI 组件库的应用(暂不共享 shadcn/ui,但可以用 Tailwind + 原生 HTML)
  • 需要服务端逻辑的应用(只支持纯前端,没有专属后端接口注册机制)
  • 强依赖全局 CSS 覆盖或复杂 Portal 主题联动的应用(当前只保证局部 CSS Modules 和非 Portal 子树变量)

这些会在后续迭代中放开。

常见问题

Q: 预览报"未找到面板组件"?

A: 大概率是 view key 和源码文件名不对齐。让 AI 检查 app.yamlviews.<key>.entry 是否等于 ./panels/<key>.js,对应源码是否在 src/panels/<key>.tsx

Q: 预览报"编译失败"?

A: AppPreview 顶部会显示编译错误,点击具体 view 的「失败」badge 看详细错误行。把错误原文发给 AI,让 AI 修。

Q: 面板里能发消息给对话区吗?

A: 能。import { chat } from '@knodo/api'; chat.send('你的消息') 就会把消息发到当前激活的对话 Tab。如果你只想预填入输入框让用户确认,用 chat.fill('...')

Q: 面板里能调用平台后端 API 吗?

A: 可以,直接 fetch('/api/v1/...', { credentials: 'include' }),凭证会自动带,后端按当前登录用户鉴权。

Q: 发布失败 409 但我是作者?

A: 重启 backend 让 DTO 字段生效(overwrite 字段是新加的)。正常情况下会弹确认对话框让你点「覆盖」。

Q: 预览模式下页面崩了,怎么回去?

A: 右下角逃生悬浮球永远可点,或者双击 ESC

Q: 发布的 App 别人看不到?

A: 检查可见性:默认是 PRIVATE(只有你自己)。在应用模板管理里编辑可见性为 INTERNAL(组织内)或 PUBLIC(跨组织)。

相关文档