Novu 官方 React Email 桥接应用模板深度解析:从 `npx novu init` 到首个邮件工作流上线
2026/9/10 16:19:47 网站建设 项目流程

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.tsxapp/api/*),负责前端展示与 HTTP 入口;
  • Novu 工作流层app/novu/workflows/中以 TypeScript 定义的工作流及其入参 Schema;
  • 邮件模板层app/novu/emails/中基于 React Email 组件库编写的邮件组件。

该模板是模板家族的成员之一,同目录下还提供app-agentapp-agent-ai-sdkapp-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:2022(Novu Dev Studio 本地开发工具的端口,在模板的app/api/dev-studio-status/route.ts与邮件按钮链接中均有引用)共同构成了本地开发环境。

Bridge 端点解剖:/api/novu如何把工作流暴露给 Novu

模板中最核心的一行代码位于 app/api/novu/route.ts:

import { 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], });

要点拆解:

  1. serve来自@novu/framework/next:这是 Novu 框架为 Next.js App Router 提供的适配器,它实现了 Bridge 协议所需的全部 HTTP 方法——GET(供 Novu 发现/健康检查)、POST(执行工作流)、OPTIONS(CORS 预检),因此只需一行导出即可完成端点接入;
  2. workflows数组:注释明确说明"workflows collection 可以容纳任意多个工作流定义",新增工作流时只需在app/novu/workflows/index.ts中导出,并追加到该数组中;
  3. 导入路径约定:模板中所有 API 路由统一通过../../novu/workflows引用工作流,保持目录职责清晰。

作为对比,模板前端app/page.tsx中的连接检测逻辑(轮询/api/dev-studio-status)进一步印证了本地开发闭环:dev-studio-status路由会以 3 秒超时探测http://localhost:2022/.well-known/novu,只有 Dev Studio 返回合法的portroute字段时,页面才将状态置为connected。这意味着,工作流从"代码定义"到"云端可触发"的过程,在本地开发阶段由 Dev Studio 承担了同步与调试的职责。

第一个工作流:双通道的 welcome-onboarding-email

模板预置了一个可直接运行的工作流welcome-onboarding-email,完整定义位于 app/novu/workflows/welcome-onboarding-email/workflow.ts:

import { 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.emailstep.inApp等),payload是触发时携带的业务数据;
  • 第三个参数是配置对象:传入payloadSchema,用于对触发载荷做类型校验与约束。

双通道演示:email + in-app

该工作流演示了两个最常用的步骤:

  1. step.email('send-email', ...):邮件步骤,controls来自用户在 Novu 工作流编辑器/Studio 中可配置的控制项(对应emailControlSchema),步骤返回的{ subject, body }即为最终邮件内容。注意body通过renderEmail(controls, payload)由 React Email 组件实时渲染为 HTML 字符串;
  2. step.inApp('in-app-step', ...):应用内通知步骤,直接引用payload中的inAppSubjectinAppBodyinAppAvatar字段。这样一次触发即可同时投递"邮件 + 站内通知"两种渠道,是理解 Novu 多通道编排的最佳入门示例。

Schema 先行:Zod 驱动的类型安全

模板把入参校验抽象为独立的 schemas.ts,使用 Zod 定义两类 Schema:

payloadSchema(触发载荷):定义触发工作流时必须/可携带的业务数据,全部带默认值,因此空载荷也能触发成功:

字段类型默认值说明
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)机制一一对应:

  • subject:string,默认A Successful Test on Novu!,控制邮件主题;
  • showHeader:boolean,默认true,控制是否显示邮件顶部的 Novu Logo;
  • components:数组,默认包含 heading / text / users / text / button 五个区块,每个元素包含type(枚举heading | text | button | code | users)、textalign(枚举left | center | right)。这套结构化的"区块数组"是模板演示的核心亮点——邮件内容本身成为可配置数据。

而 types.ts 通过z.infer从 Schema 反推 TypeScript 类型(PayloadSchemaControlSchema),让邮件组件与工作流共享同一份类型契约,从编译期杜绝字段拼写错误。

React Email 渲染链路:从组件到 HTML

模板的邮件组件位于 app/novu/emails/novu-onboarding-email.tsx,其技术要点如下:

组件构成

  • @react-email/components引入HtmlHeadPreviewTailwindBodyContainerSectionHeadingTextButtonRowColumnImgCodeInline等全套 React Email 组件;
  • 通过<Tailwind config={...}>自定义主题:新增brand: '#2250f4'offwhiteblurwhite等颜色变量与 0/20/45px 间距变量,实现零额外 CSS 文件的邮件样式;
  • 组件 Props 类型为NovuWelcomeEmailProps = ControlSchema & PayloadSchema,即把工作流的控制项与载荷合并注入。

区块渲染逻辑

邮件主体按components数组动态渲染五种区块:

  • heading:渲染<Heading as="h1">,对齐方式来自component.align
  • button:渲染指向http://localhost:2022(Novu Dev Studio)的黑色按钮;
  • text:渲染正文<Text>
  • users:渲染"用户邀请"三列头像行(userImagearrowImageteamImage),模拟真实产品中的社交型通知;
  • code:使用<CodeInline>展示内联代码片段。

导出renderEmail工具函数

文件底部是关键衔接点:

export function renderEmail(controls: ControlSchema, payload: PayloadSchema) { return render(<NovuWelcomeEmail {...controls} {...payload} />); }

renderEmail调用@react-email/componentsrender将 React 组件树转为 HTML 字符串,供工作流中step.emailbody使用。这正是"React Email 写模板、Novu 负责投递"的 Code-First 模式的精髓:邮件模板与业务代码同仓库、同类型、同版本管理。

触发工作流:模板自带的演示链路

模板不仅定义了工作流,还自带了一条完整的前后端触发演示链路:

1. 服务端触发 API:app/api/trigger/route.ts

export 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 API),to为订阅者 ID(取自环境变量NEXT_PUBLIC_NOVU_SUBSCRIBER_ID),payload为空对象——得益于 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 头中。

扩展指引:如何加入你自己的工作流

依据模板的代码组织方式,添加新工作流的推荐步骤为:

  1. app/novu/workflows/下新建目录(如my-workflow/),参考welcome-onboarding-email拆分为workflow.tsschemas.tstypes.ts三个文件;
  2. schemas.ts中用 Zod 定义payloadSchema与各步骤的controlSchema,保持字段默认值完备,确保空载荷也能演示;
  3. workflow.ts中用workflow()声明工作流,按需调用step.emailstep.inAppstep.smsstep.push等步骤;
  4. 在 app/novu/workflows/index.ts 中export *新模块;
  5. 把新工作流追加到 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),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询