@yichong6/canva-scaffold
v0.1.0
Published
Canva application source templates and command-line scaffolding tools
Readme
Canva 应用脚手架
脚手架提供完整的新应用起步工程,以及可定向升级的公共源码。生成后的应用独立安装、构建和发布;@yichong6/canva-core 继续作为纯后端 SDK 使用,不引入 React 或 Canva 依赖。
旧项目的提取依据、组件归属和取舍见 架构与提取说明,官方素材操作及权限见 Canva 接入说明。
创建新应用
使用 Node 22 或 24。以下 npm 命令在公开发布完成后可用;目前仓库配置为 public / alpha,并不代表版本已经上传。
npm exec --registry=https://registry.npmjs.org/ --package=@yichong6/[email protected] -- \
create-canva-app --channel my_image_app --name "My Image App" --port 8082
cd my_image_app
npm install
npm run lint:check
npm test -- --runInBand
npm run build默认在执行命令的位置创建 <channel> 目录,生成 50 个文件。已有 Canva App ID 时增加 --app-id YOUR_APP_ID;--directory apps/my_image_app 可指定新目录,其父目录必须已存在。已有目标一律拒绝覆盖;输出路径不能包含 ..,其他位置可显式使用绝对路径。--help 查看全部参数。
渠道必须在 usa 登记;生成器不会注册渠道或 Canva 应用,也不自动安装依赖或调用后端。默认依赖精确的 @yichong6/[email protected],所以应先发布 core,再发布此脚手架。
在 new_canva 仓库内联调时,显式指定本地 core:
node package/scaffold/scripts/create_app.mjs \
--channel my_image_app --name "My Image App" --port 8082 \
--directory apps/my_image_app --core-path package/core
cd package/core
npm ci
npm run build
cd ../../apps/my_image_app
npm install--core-path 相对执行命令的位置解析,校验包名后写入相对 file: 依赖;它仅用于本地联调。新应用首次安装产生自己的 package-lock.json,审查并提交后使用 npm ci。不复制真实应用的 .env、模型、素材、依赖、缓存或锁文件。
公开分发保留版权,license: UNLICENSED;已授权团队按既有授权使用。详见 版权说明。Canva 原始组件及衍生内容继续遵守模板中的 Canva 许可证,该文本随应用生成;公开下载不授予公司后端服务权限。
接入业务时主要修改:
app.json:自己的身份、API 地址、计费单位和免费额度解释方式。src/generation/model.ts:已确认的 owner/name、输入构造、单价和输出解析。src/generation/definition.ts、src/pages/index.tsx:产品字段和校验。src/generation/actions.ts:产品成功条件、保存及记账时机。src/canva/add_to_design.ts:产品结果到 Canva 素材的映射。
起步产品是文本生成单张 PNG 图片。默认模型、价格及免费额度模式未确认,因此不会发起生成或消费。它保留了 index → progress → result、文本审核、原任务恢复和不确定消费保护,开发者只在完成合同配置后启用真实生成。它不是视频、音频、文本所有产品的万能工作流。
目录和两种维护方式
package/scaffold/
├── templates/app/ 创建一次:入口、公开配置、产品页面、示例业务流程与测试
├── templates/common-ui/ 可定向升级:公共 UI、账户 hooks、样式及 Canva helpers
├── bin/ npm 命令入口(create-canva-app / sync-canva-ui)
├── scripts/create_app.mjs 创建完整的新应用
├── scripts/sync_common_ui.mjs
├── tests/ 创建和同步的文件安全测试
├── ARCHITECTURE.md 旧项目来源、分层和组件职责
└── CANVA_REFERENCE.md 官方素材/选区接入说明templates/app 中的业务与配置文件生成后归应用维护。templates/common-ui 中的公共源码才由同步工具管理;允许升级的准确路径以 scripts/sync_common_ui.mjs 的 commonUiFiles 为准。同步不会覆盖应用身份、环境文件、页面、模型和业务 actions。
公共源码编译进应用,Canva 在每个应用构建时提取它的翻译文案。浏览器不加载模板目录,也不存在另一套运行时 React UI 包。更新模板不会自动影响已发布应用。
公共能力
| 文件 | 作用 | 谁提供业务差异 |
| --- | --- | --- |
| components/app_shell.tsx | 唯一纵向滚动容器、Canva 主题间距与滚动条 | 应用注入内容 |
| components/page_layout.tsx | 顶部提示、页面内容、底部额度的固定顺序 | 表单和按钮属于页面 |
| components/generation_progress.tsx | 旧版居中标题、横向进度条、说明和返回按钮 | 应用传阶段文案和返回行为 |
| components/error_alert.tsx | 优先展示 core 的用户可见错误信息 | 应用传本地化兜底文案 |
| components/app_error_boundary.tsx | React 渲染失败时显示可读提示 | 可选错误回调;没有隐式远程上报 |
| components/image_preview.tsx | 自然比例完整图片、加载失败与重载 | 应用传 URL、alt;不重新生成 |
| components/account_notice.tsx | 登录失败及手动重试 | 页面外层传账户状态 |
| components/quota_footer.tsx | 七类额度、加载转圈、支付入口、返回刷新 | core 计算额度;应用传名称和成本 |
| hooks/use_canva_account.ts | 订阅 core 账户快照 | 唯一 client |
| hooks/use_account_session.ts | 自动登录、语言桥接、失败重试 | 应用生命周期只挂载一次 |
| canva/ | 图片上传/插入、文本插入、安全选区监听 | MIME、alt、AI 声明和产品数据 |
| styles/scaffold.css | 页面、进度与图片的共用样式 | 产品专属样式写 components.css |
进度条是等待动画,不是服务器百分比,不显示数字,也不会走到 100 后自行跳转。审核阶段返回可停止尚未创建任务的检查;提交任务后的返回只停止界面等待。实际语义仍由应用 actions 决定。
footer 沿用旧版加载时的居中 medium 转圈,无可见 Signing in。needUsage 只显示已确认成本,不能决定扣费。支付链接继续服从 core 的审核与平台规则;从外部页面返回只刷新账户,不能当作付款成功。
升级已有应用
通过 npm 安装的版本同样支持公共源码同步:
npm exec --registry=https://registry.npmjs.org/ --package=@yichong6/[email protected] -- \
sync-canva-ui --check ./my_image_app
# 审查差异后,改为 --write;已有不同内容时需显式加 --overwrite。仓库内也可以直接执行脚本:
# 默认只读;不一致时退出码为 1。
node package/scaffold/scripts/sync_common_ui.mjs --check apps/ai_cover_generator apps/demo
# 安装缺失公共文件;遇到已有不同内容会拒绝整次应用写入。
node package/scaffold/scripts/sync_common_ui.mjs --write apps/my_image_app
# 阅读差异后,明确采用模板版本。
node package/scaffold/scripts/sync_common_ui.mjs --write --overwrite apps/my_image_app
node --test package/scaffold/tests/*.test.mjs脚本先检查单个应用的全部目标,拒绝符号链接应用及中间目录/文件。多个应用按顺序处理,不承诺跨应用事务。--write 只安装源码,不修改依赖、自动接入页面或发布;旧应用首次接入需按架构说明添加 imports/props 并移除重复布局。
与 core 的协作
flowchart LR
Create[create_app] --> App[新应用源码]
Common[公共组件与 Canva helpers] -->|同步| App
App -->|账户/审核/任务/上传/额度| Core[canva-core]
App -->|素材与设计操作| Canva[Canva 官方 SDK]
Core --> USA[usa 账户与消费]
Core --> API[external_api 模型与审核]客户端每个应用只创建一次。不要在 footer 或页面切换中另建 client。账户状态由 core 维护,UI 只订阅;模型映射由后端处理,前端应用仍提供 owner/name/input。图片保存到 R2 与上传到 Canva 是两个阶段;后者重试不再创建模型或消费积分。
core 的 reporting 仍没有完整上报实现,本脚手架不会复制旧项目的硬编码 Token,也不会假称飞书上报已接入。源码仓库保留 validation/2026-10-09/scaffold-verification.json 等验证记录,npm 包不携带本机验证资料。
维护者打包验证
在脚手架源码目录运行 npm test 和 npm pack,检查真实压缩包的文件清单与命令入口。npm run check:release 会执行测试和实际 tarball 的离线安装、创建与同步验收。发布时使用已验证的同一 tarball;源码门禁不会在直接上传 tgz 时重新执行。完整发布步骤见源码仓库 docs/Canva-npm公开发布.md。
安装与构建版本合同
应用模板将 @canva/app-scripts 下的 @rspack/core override 写为明确的 2.0.8,与根 devDependencies 的版本一致。这里不使用 $@rspack/core 引用:npm 10.9.8 在首次解析某些 peer dependency 树时无法解析该引用,导致空目录安装失败。升级 Rspack 时应同步修改两个版本,并从新生成的应用执行首次安装验证。
构建链也按已验证组合固定:@canva/app-scripts 为 1.1.2;其依赖通过 overrides 固定为 @rsbuild/[email protected]、@rsbuild/[email protected]、@rsbuild/[email protected] 和 @rspack/[email protected]。保留 @swc/[email protected] 与 @swc/[email protected]。原因是 scripts 的 ^2.0.11 间接依赖会在首次安装漂移到 Rsbuild 2.2.x,其最低 Rspack 要求高于模板固定版本。升级时整体评估这个组合,并在无 lock、无 node_modules 的新应用中执行 install、types、lint、test、build;仅验证旧应用的现有 lock 不能证明新脚手架可以安装构建。
