get-convex / get-convex/resend

README: React Email render() works in regular actions; document static rendering for mutations

Open Beginner friendly
#116 1 comment 0 reactions 0 assignees View on GitHub
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.