Skip to content

fix(ui): update existing Resend template on upload instead of duplicating#3572

Open
Maliik-B wants to merge 1 commit into
resend:canaryfrom
Maliik-B:fix/resend-template-update-on-upload
Open

fix(ui): update existing Resend template on upload instead of duplicating#3572
Maliik-B wants to merge 1 commit into
resend:canaryfrom
Maliik-B:fix/resend-template-update-on-upload

Conversation

@Maliik-B

@Maliik-B Maliik-B commented Jun 15, 2026

Copy link
Copy Markdown

Closes #3194.

Problem

The "Upload to Resend" and "Bulk Upload" buttons in the preview server's Resend toolbar always call resend.templates.create(), so every upload of the same template creates a brand new template (welcome, welcome (1), welcome (2), ...). The template ID your app code references keeps pointing at the original, outdated version, which makes the integration unusable as a sync mechanism.

Fix

This takes the smaller of the two approaches discussed in the issue. Before creating, exportSingleTemplate looks the template up by name via resend.templates.list():

  • exactly one match: resend.templates.update(id, { html }), updating it in place
  • zero or multiple matches: resend.templates.create(...), the previous behavior

Resend template names are not unique, so the exactly-one guard avoids editing the wrong template. The action's return shape is unchanged, and both the single Upload and Bulk Upload paths run through exportSingleTemplate, so both are covered.

The sync logic is extracted into a plain uploadTemplateToResend(resend, template) helper so it can be unit tested directly, leaving the server action a thin wrapper.

Known limitations (intentional, deferred to a follow-up)

  • templates.list() returns a single page, so a template beyond the first page falls back to create.
  • Bulk Upload now issues one list() per template on top of the existing 600ms throttle, which sits close to the 2 requests/second limit.

Both are fully resolved by the react-email.config.ts slug-to-ID mapping from the issue, which removes the need to list at all. That is a larger surface and reads better as its own follow-up PR, as discussed in the thread.

Tests

Adds upload-template-to-resend.spec.ts covering create (no match), update (one match), create fallback (multiple matches), name-mismatch, and the list / update / create error paths with a mocked Resend SDK. No existing tests were changed.

Thanks @gabrielmfern for the go-ahead and @cooperjbrandon for handing it off.


Summary by cubic

Stops duplicate Resend templates by updating the existing template on upload when exactly one name match is found. Applies to both "Upload to Resend" and "Bulk Upload" so re-uploads now sync to the same template ID (fixes #3194).

  • Bug Fixes
    • Look up via resend.templates.list(); update with resend.templates.update(id, { html }) on a single match; fall back to resend.templates.create(...) otherwise.
    • Moved sync logic to uploadTemplateToResend(resend, template) and routed exportSingleTemplate through it.
    • Added unit tests covering create, update, multi-match fallback, name mismatch, and error paths.

Written for commit 44d40b0. Summary will update on new commits.

Review in cubic

…ting

The "Upload to Resend" and "Bulk Upload" actions always called
resend.templates.create(), so re-uploading the same template created a
duplicate (welcome, welcome (1), ...) and left the template ID referenced by
app code pointing at the stale version.

Look the template up by name via resend.templates.list() and update it in
place when exactly one matches, falling back to create() on zero or multiple
matches. Resend template names are not unique, so the exactly-one guard avoids
editing the wrong template.

Closes resend#3194
@vercel

vercel Bot commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

@Maliik-B is attempting to deploy a commit to the resend Team on Vercel.

A member of the Team first needs to authorize it.

@changeset-bot

changeset-bot Bot commented Jun 15, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 44d40b0

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
@react-email/ui Patch
react-email Patch
@react-email/editor Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 4 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Requires human review: This PR changes template create vs update logic in the Resend upload path and requires domain knowledge; it should be reviewed by a human to ensure production correctness.

Re-trigger cubic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Resend integration always creates duplicate templates instead of updating existing ones

1 participant