ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Novu 官方 React Email 桥接应用模板深度解析:从 `npx novu init` 到首个邮件工作流上线

Novu 官方 React Email 桥接应用模板深度解析:从 `npx novu init` 到首个邮件工作流上线 Novu 官方 React Email 桥接应用模板深度解析从npx novu init到首个邮件工作流上线【免费下载链接】novuThe open-source communication infrastructure for agents and products项目地址: https://gitcode.com/GitHub_Trending/no/novu导读packages/novu/src/commands/init/templates/app-react-email/ts/是 Novu CLI 初始化命令npx novu init生成的一套开箱即用的桥接Bridge应用模板它以 Next.js 为运行载体将 React Email 编写的邮件模板与 Novu 工作流无缝衔接。读完本文你将掌握模板的整体目录结构、Bridge 端点的工作原理、工作流与 Zod Schema 的声明方式、React Email 模板的渲染链路以及如何在本地一键触发你的第一条测试通知。模板是什么一条命令生成的 Code-First 通知应用模板的说明文档README-template.md明确指出这是一套由npx novu init引导生成的 Novu 桥接应用。它体现了 Novu 的代码优先Code-First理念——工作流、邮件模板、Schema 全部以 TypeScript 源码的形式存在于你的仓库中而不是在云端拖拽配置。从模板目录结构packages/novu/src/commands/init/templates/app-react-email/ts/可以看到生成后的应用包含三大部分Next.js 应用层app/下的页面与 API 路由app/page.tsx、app/api/*负责前端展示与 HTTP 入口Novu 工作流层app/novu/workflows/中以 TypeScript 定义的工作流及其入参 Schema邮件模板层app/novu/emails/中基于 React Email 组件库编写的邮件组件。该模板是模板家族的成员之一同目录下还提供app-agent、app-agent-ai-sdk、app-agent-langchain等变体见 templates 目录而本模板的差异化定位是用 React Email 编写可交互、可动态渲染的邮件内容并以 email in-app 双通道演示完整工作流。快速启动四种包管理器一键运行模板 README 给出的启动方式极为简洁四种包管理器任选其一npm run dev # or yarn dev # or pnpm dev # or bun dev启动后 Next.js 开发服务器默认监听http://localhost:4000同时通过默认 Bridge 端点/api/novu与 Novu Cloud 同步状态。也就是说你的工作流定义会被暴露为一个标准的 HTTP 端点Novu Cloud 会拉取同步该端点上的工作流清单并在运行时回调该端点执行对应步骤。这里有两个关键概念值得展开Bridge 端点模板中即app/api/novu/route.ts它把工作流集合暴露为可被 Novu 服务调用的协议端点端口约定默认 4000 端口与http://localhost:2022Novu Dev Studio 本地开发工具的端口在模板的app/api/dev-studio-status/route.ts与邮件按钮链接中均有引用共同构成了本地开发环境。Bridge 端点解剖/api/novu如何把工作流暴露给 Novu模板中最核心的一行代码位于 app/api/novu/route.tsimport { serve } from novu/framework/next; import { welcomeOnboardingEmail } from ../../novu/workflows; // the workflows collection can hold as many workflow definitions as you need export const { GET, POST, OPTIONS } serve({ workflows: [welcomeOnboardingEmail], });要点拆解serve来自novu/framework/next这是 Novu 框架为 Next.js App Router 提供的适配器它实现了 Bridge 协议所需的全部 HTTP 方法——GET供 Novu 发现/健康检查、POST执行工作流、OPTIONSCORS 预检因此只需一行导出即可完成端点接入workflows数组注释明确说明workflows collection 可以容纳任意多个工作流定义新增工作流时只需在app/novu/workflows/index.ts中导出并追加到该数组中导入路径约定模板中所有 API 路由统一通过../../novu/workflows引用工作流保持目录职责清晰。作为对比模板前端app/page.tsx中的连接检测逻辑轮询/api/dev-studio-status进一步印证了本地开发闭环dev-studio-status路由会以 3 秒超时探测http://localhost:2022/.well-known/novu只有 Dev Studio 返回合法的port与route字段时页面才将状态置为connected。这意味着工作流从代码定义到云端可触发的过程在本地开发阶段由 Dev Studio 承担了同步与调试的职责。第一个工作流双通道的 welcome-onboarding-email模板预置了一个可直接运行的工作流welcome-onboarding-email完整定义位于 app/novu/workflows/welcome-onboarding-email/workflow.tsimport { workflow } from novu/framework; import { renderEmail } from ../../emails/novu-onboarding-email; import { emailControlSchema, payloadSchema } from ./schemas; export const welcomeOnboardingEmail workflow( welcome-onboarding-email, async ({ step, payload }) { await step.email( send-email, async (controls) { return { subject: controls.subject, body: renderEmail(controls, payload), }; }, { controlSchema: emailControlSchema, } ); await step.inApp(in-app-step, async () { return { subject: payload.inAppSubject, body: payload.inAppBody, avatar: payload.inAppAvatar, }; }); }, { payloadSchema, } );理解workflow声明式 API第一个参数是工作流 ID 字符串welcome-onboarding-email它在整个环境中唯一标识该工作流也是后续触发trigger时使用的名称第二个参数是执行函数接收{ step, payload }其中step暴露各类通道步骤step.email、step.inApp等payload是触发时携带的业务数据第三个参数是配置对象传入payloadSchema用于对触发载荷做类型校验与约束。双通道演示email in-app该工作流演示了两个最常用的步骤step.email(send-email, ...)邮件步骤controls来自用户在 Novu 工作流编辑器/Studio 中可配置的控制项对应emailControlSchema步骤返回的{ subject, body }即为最终邮件内容。注意body通过renderEmail(controls, payload)由 React Email 组件实时渲染为 HTML 字符串step.inApp(in-app-step, ...)应用内通知步骤直接引用payload中的inAppSubject、inAppBody、inAppAvatar字段。这样一次触发即可同时投递邮件 站内通知两种渠道是理解 Novu 多通道编排的最佳入门示例。Schema 先行Zod 驱动的类型安全模板把入参校验抽象为独立的 schemas.ts使用 Zod 定义两类 SchemapayloadSchema触发载荷定义触发工作流时必须/可携带的业务数据全部带默认值因此空载荷也能触发成功字段类型默认值说明inAppSubjectstring**Welcome to Novu!**站内通知标题inAppBodystringThis is an in-app notification powered by Novu.站内通知正文inAppAvatarstring(url)Novu GitHub 头像 URL站内通知头像teamImagestring(url)Spr.so 渐变图 URL邮件用户邀请区块团队头像userImagestring(url)react-email demo 用户图 URL邮件用户邀请区块用户头像arrowImagestring(url)react-email demo 箭头图 URL邮件用户邀请区块箭头图标emailControlSchema邮件控制项定义邮件在 Novu 工作流画布中可被配置的控制项这与 Novu 可视化编辑器的控件Controls机制一一对应subjectstring默认A Successful Test on Novu!控制邮件主题showHeaderboolean默认true控制是否显示邮件顶部的 Novu Logocomponents数组默认包含 heading / text / users / text / button 五个区块每个元素包含type枚举heading | text | button | code | users、text、align枚举left | center | right。这套结构化的区块数组是模板演示的核心亮点——邮件内容本身成为可配置数据。而 types.ts 通过z.infer从 Schema 反推 TypeScript 类型PayloadSchema与ControlSchema让邮件组件与工作流共享同一份类型契约从编译期杜绝字段拼写错误。React Email 渲染链路从组件到 HTML模板的邮件组件位于 app/novu/emails/novu-onboarding-email.tsx其技术要点如下组件构成从react-email/components引入Html、Head、Preview、Tailwind、Body、Container、Section、Heading、Text、Button、Row、Column、Img、CodeInline等全套 React Email 组件通过Tailwind config{...}自定义主题新增brand: #2250f4、offwhite、blurwhite等颜色变量与 0/20/45px 间距变量实现零额外 CSS 文件的邮件样式组件 Props 类型为NovuWelcomeEmailProps ControlSchema PayloadSchema即把工作流的控制项与载荷合并注入。区块渲染逻辑邮件主体按components数组动态渲染五种区块heading渲染Heading ash1对齐方式来自component.alignbutton渲染指向http://localhost:2022Novu Dev Studio的黑色按钮text渲染正文Textusers渲染用户邀请三列头像行userImage、arrowImage、teamImage模拟真实产品中的社交型通知code使用CodeInline展示内联代码片段。导出renderEmail工具函数文件底部是关键衔接点export function renderEmail(controls: ControlSchema, payload: PayloadSchema) { return render(NovuWelcomeEmail {...controls} {...payload} /); }renderEmail调用react-email/components的render将 React 组件树转为 HTML 字符串供工作流中step.email的body使用。这正是React Email 写模板、Novu 负责投递的 Code-First 模式的精髓邮件模板与业务代码同仓库、同类型、同版本管理。触发工作流模板自带的演示链路模板不仅定义了工作流还自带了一条完整的前后端触发演示链路1. 服务端触发 APIapp/api/trigger/route.tsexport async function POST() { try { await welcomeOnboardingEmail.trigger({ to: process.env.NEXT_PUBLIC_NOVU_SUBSCRIBER_ID || , payload: {}, }); return NextResponse.json({ message: Notification triggered successfully }); } catch (error: unknown) { const errorMessage error instanceof Error ? error.message : Unknown error occurred; console.error(Error triggering notification:, errorMessage); return NextResponse.json({ message: Error triggering notification, error: errorMessage }, { status: 500 }); } }通过welcomeOnboardingEmail.trigger(...)以 SDK 方式直接触发工作流而非走 REST APIto为订阅者 ID取自环境变量NEXT_PUBLIC_NOVU_SUBSCRIBER_IDpayload为空对象——得益于 Schema 默认值空载荷依然能产出完整通知异常分支将错误信息以 500 状态码返回便于在页面上排查。2. 前端交互app/page.tsx页面加载时向/api/events上报一次访问埋点透传到https://api.novu.co/v1/telemetry/measure见 app/api/events/route.ts同时每 3 秒轮询/api/dev-studio-status以展示已连接状态。点击页面按钮后调用/api/trigger触发通知成功后弹出成功提示3 秒后自动隐藏。页面中还集成了NovuInbox组件app/components/NotificationToast/Notifications.tsx用于实时接收 in-app 通知。3. 环境变量从代码中可以确认模板运行所需的两个环境变量NEXT_PUBLIC_NOVU_SUBSCRIBER_ID触发通知时使用的订阅者标识前端可访问NOVU_SECRET_KEY服务端调用 Novu API如遥测上报时使用的密钥以ApiKey前缀放在 Authorization 头中。扩展指引如何加入你自己的工作流依据模板的代码组织方式添加新工作流的推荐步骤为在app/novu/workflows/下新建目录如my-workflow/参考welcome-onboarding-email拆分为workflow.ts、schemas.ts、types.ts三个文件在schemas.ts中用 Zod 定义payloadSchema与各步骤的controlSchema保持字段默认值完备确保空载荷也能演示在workflow.ts中用workflow()声明工作流按需调用step.email、step.inApp、step.sms、step.push等步骤在 app/novu/workflows/index.ts 中export *新模块把新工作流追加到 app/api/novu/route.ts 的serve({ workflows: [...] })数组中。至此新工作流会随/api/novu端点被 Novu 发现进入与welcome-onboarding-email完全相同的同步与触发链路。小结app-react-email模板是理解 Novu Code-First 通知基础设施的最佳切入点它以 Next.js React Email Zod Novu Framework 的组合把工作流声明、Schema 校验、邮件渲染、Bridge 同步、SDK 触发整条链路浓缩在不到十个源文件中。无论你是想快速跑通第一条通知还是准备把现有 Next.js 项目接入 Novu都可以直接以该模板为蓝本开始改造。【免费下载链接】novuThe open-source communication infrastructure for agents and products项目地址: https://gitcode.com/GitHub_Trending/no/novu创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进