get-convex / get-convex/resend
README: React Email render() works in regular actions; document static rendering for mutations
- Dominant language
- TypeScript
- Stars
- 39
- Forks
- 25
- Avg merge
- 2d 13h
- Merged PRs (30d)
- 2
Description
> [!NOTE]
> Fable 5 sent this message on behalf of @Paul1365972
The README's React Email section warns that it "must run in a Convex Node action and not a regular Action". That was accurate when it was written in July 2025: with React 19 and the then-current @react-email/render 1.1.3, a regular action crashed on react-dom's module-scope `MessageChannel`. It has been outdated since @react-email/render 1.2.3 (September 2025), which added a `convex` export condition that selects an edge build using `react-dom/server.edge` (resend/react-email#2438, "use react-dom edge export in convex runtime"). I verified in a freshly scaffolded project on convex 1.45.0, react-dom 19.2.8, and @react-email/render 2.1.0: `render()` works in a regular action, and `"use node"` changes nothing.
`render()` still fails in queries and mutations with `Uncaught TypeError: dynamic module import unsupported`, since it imports react-dom dynamically and those scopes are created with dynamic imports disabled. But mutations can render the same templates with a static import: `renderToStaticMarkup` from `react-dom/server.edge` (react-dom 19+), the XHTML doctype that `render()` normally prepends, and `toPlainText` for the text body. I verified this works.
This matters because `sendEmail` accepts a mutation ctx. Enqueueing in the mutation that triggered the email commits atomically with the triggering write. The Node-action pattern loses that: failed actions are not retried, and retrying by hand can double-enqueue until enqueue-time idempotency lands (#107 / #108).
Could the README:
1. Show `render()` in a regular action, without `"use node"`.
2. Add the mutation variant with the static renderer, noting it needs react-dom 19. Should resend/react-email#2529 get fixed upstream, this simplifies to plain `render()` in a mutation.
Contributor guide
Research direction
Start with the README's React Email section and its current warning about regular actions. Update the documentation to show render() in a regular action and add the mutation example using renderToStaticMarkup, the XHTML doctype, and toPlainText; note the React 19 requirement and the possible upstream simplification.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- react, typescript
- Domain
- documentation
- Issue type
- Documentation
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100