Native Shell
Native Shell:AI 生成的 UI,在你的应用中原生呈现,覆盖每个平台。iOS、Android、macOS、Windows 与 Linux 上的应用、GPUI 应用与网页在运行时加载已签名、沙箱隔离的 TSX 模块并绘制 th
AI 翻译
尚未检测到更新。GitHub 发布版本后会显示在这里。
个人 GitHub 账号下公开仓库的所有者可以登录并验证所有权,自行管理介绍,无需管理员批准。
登录并生成验证文件,在 30 分钟内将其提交到此仓库的默认分支。其他分支或分叉仓库中的文件无效。然后在下方检查文件,即可无需管理员批准直接管理项目。请保留文件以维持管理权限。
如需登录,将前往登录页面。登录后请回到此处,再次点击所选的验证按钮。
在项目文件夹中运行 /nomorevibe verify,即可验证所有权并自行管理介绍。
一分钟完成验证Email Sender API, deploy in your Free Cloudflare Accont to user like a service
翻译准备中
取自仓库 README
正在加载完整 README。
查看完整 README ↗A self-hosted transactional email service for Cloudflare Workers. Your backends call one authenticated REST API, and notify-flow renders the email from a template and sends it over plain SMTP to Gmail, Microsoft 365 or any other SMTP server. It does not depend on Resend, SendGrid, Mailgun or similar platforms. It can also send Web Push notifications to your users' phones and computers, opt-in per client.
[!IMPORTANT] There is no shared public instance. Each person or team deploys their own notify-flow, in their own Cloudflare account, with their own D1 database, queue and SMTP mailbox, and connects their own apps to it. The author's deployment is private and is not offered as a service: don't point your apps at it. The AI integration prompt walks you through your own deploy and the integration into your site.
[!NOTE] The MVP is implemented: emails are sent by template name or by event, synchronously or asynchronously through Cloudflare Queues, and data lives in Cloudflare D1. The Roadmap lists what comes next.
[!TIP] Adding email to your web app? Follow the web app integration guide: a step-by-step walkthrough with backend code samples. Or paste the AI integration prompt into a coding agent and let it do the work, then the AI management page prompt to get an admin page with statistics and template editing. For push notifications only, without email, use the AI Web Push prompt.
Every app ends up sending the same emails: welcome, email verification, password reset, login alerts. notify-flow keeps those emails in one place:
it, en and pt-BR.Frontend ──► Your backend ──► notify-flow (Worker) ──► SMTP server ──► Recipient
│ │
│ ├─ authenticate the client (API key)
│ ├─ validate payload and rate limit
│ ├─ pick the template (by name or event), render subject, HTML, text
│ ├─ send over TLS / STARTTLS, now or from a queue, retrying transient errors
│ └─ log the delivery in D1
└─ owns auth logic (tokens, reset URLs, user checks)
notify-flow only delivers mail. Security logic such as generating reset tokens stays in your backend.
You need Node.js 20+ and your own Cloudflare account (sign up): every deployment is independent, so the commands below create the Worker, database and queue in your account.
npm install
cp wrangler.jsonc.example wrangler.jsonc # git-ignored: fill in your database_id before deploying
npm run db:migrate:local
npm run client:create -- my-app # prints the API key once
cp .dev.vars.example .dev.vars # fill in your SMTP credentials
npm run dev # admin dashboard: http://localhost:8787/admin/ (not 127.0.0.1)
To deploy:
npx wrangler d1 create notify-flow # copy the database_id into wrangler.jsonc
npm run db:migrate:remote # on upgrades too: migrate before npm run deploy
npx wrangler queues create notify-flow-emails # once: the async send queue
npx wrangler secret put SMTP_USERNAME # repeat for SMTP_PASSWORD, SMTP_FROM_EMAIL, SMTP_FROM_NAME
npx wrangler secret put ADMIN_SETUP_TOKEN # long random string, used once to register the /admin account
npm run deploy
npm run client:create -- my-app --remote
For development:
npm test # vitest inside workerd, with a local D1
npm run typecheck # regenerates worker types, then tsc
A web app sends email through your own deployment (see Getting started) in three steps:
npm run client:create -- <app-name> --remote once per app, then store the key and your Worker's URL as secrets in the app's backend.POST /v1/email/send with a template, a recipient and the template's variables, or POST /v1/notifications with an event instead of a template. The frontend never calls notify-flow.429 and 500 with the same Idempotency-Key. Treat 4xx as integration bugs.The web app integration guide covers the details: architecture, Node.js and Python clients, password reset and sign-up flows, custom templates, retry rules, asynchronous sending and a production checklist.
Web Push is optional and opt-in per client: notify-flow can also notify a user's phone or computer while your app is closed, with a title and a short body from a built-in template, never user-written text. The operator sets the VAPID keys once and switches push on per client (setup). Your backend then registers each device and calls POST /v1/push/send. The Web Push guide has the browser, service worker and backend code.
The Worker also serves a monitoring page at /admin/: delivery stats and search, a log of errors and rejected requests, a SQL console on the D1 database, and a Clients panel with the per-client Web Push switch. There is one admin account, registered on the first visit with the ADMIN_SETUP_TOKEN secret and kept separate from client API keys. The admin dashboard guide covers setup, upgrades of an existing deployment, and what each section shows.
Every /v1/* route needs an API key, sent as Authorization: Bearer <key> or X-API-Key: <key>. A send is one call:
POST /v1/email/send
Authorization: Bearer <API_KEY>
Idempotency-Key: password-reset:user-123:request-456
Content-Type: application/json
{
"template": "password-reset",
"to": "[email protected]",
"locale": "it",
"variables": {
"appName": "Acme",
"name": "Mario",
"resetUrl": "https://app.example.com/reset-password?token=..."
}
}
{ "id": "msg_…", "status": "submitted" }
The API Reference documents every endpoint, field rule, error code and status: sending, events, templates and health, and the opt-in Web Push.
Credentials are stored as Cloudflare Secrets, never in the repository or in code.
| Name | Where | Value |
|---|---|---|
SMTP_PROVIDER | vars in wrangler.jsonc | gmail, microsoft or generic |
SMTP_HOST, SMTP_PORT, SMTP_SECURITY | vars, optional | Override the preset (SMTP_SECURITY is tls or starttls) |
SMTP_AUTH_TYPE | vars, optional | plain or login (default: per preset) |
SMTP_USERNAME, SMTP_PASSWORD | secret | SMTP account credentials |
SMTP_FROM_EMAIL, SMTP_FROM_NAME | secret | Sender identity |
| Preset | Host | Port, security and auth |
|---|---|---|
gmail | smtp.gmail.com | 465 with TLS, AUTH PLAIN; needs an app password |
microsoft | smtp.office365.com | 587 with STARTTLS, AUTH LOGIN |
generic | set SMTP_HOST | 587 with STARTTLS, AUTH PLAIN |
[!WARNING] Microsoft 365 requires SMTP AUTH to be enabled on the sending mailbox, and Security Defaults block it. Microsoft is also retiring basic authentication for SMTP AUTH. If you use this preset, plan for OAuth2 (XOAUTH2 is on the roadmap).
Idempotency-Key never sends a duplicate email or push./v1/push/*, a separate budget), RECIPIENT_LIMIT_PER_HOUR (default 5) emails per recipient and template for each client, and PUSH_LIMIT_PER_HOUR (default 60) pushes per user and conversation. Failed sends do not count.src/
├── index.ts # Worker entry point and router
├── admin/ # dashboard API: setup, login, sessions, stats, logs, SQL, clients
├── push/ # Web Push: VAPID and encryption, subscriptions, sender
├── routes/ # email, notifications, events, templates, health
├── security/ # auth, payload validation, rate limiting
├── services/ # email-service (idempotency, retries, delivery log), queue-consumer (async sends), logger (app_logs)
├── templates/ # renderer, built-in defaults, built-in events
├── smtp/ # SMTP client + provider presets
└── types/
public/admin/ # dashboard pages, served as static assets
migrations/ # D1 schema
scripts/ # create-client.mjs, vapid-keys.mjs
test/ # vitest, runs inside workerd
docs/ # docs site (VitePress): guides, API Reference; specs and plans are not published
The docs/ folder doubles as a VitePress site: Home, Documentation and API Reference, built from these Markdown files (specs, plans and handoffs are not published).
npm run docs:dev # local site with hot reload
npm run docs:build # static build in docs/.vitepress/dist; fails on dead links
npm run docs:preview # serve the build
To publish it, connect the repository to Cloudflare Pages with these settings:
| Setting | Value |
|---|---|
| Project name | notify-flow-docs |
| Production branch | main |
| Build command | npm run docs:build |
| Build output directory | docs/.vitepress/dist |
| Environment variable | NODE_VERSION=22 |
These items come from the spec and are planned after the MVP:
X-Client-Id, X-Timestamp, X-Signature)