#Problem integrating react-email into an internal action

41 messages · Page 1 of 1 (latest)

haughty urchin
#

Hi, I'm trying to send email from a convex action, using https://resend.com/ and https://github.com/resend/react-email. It's a next.js 13 app.

The resend integration is working, it's just a simple call to their SDK. But when I try to integrate react-email, the convex functions won't deploy.

My action (in /convex/email.ts) imports and calls a function from another module (in /convex/src/email/new_share.ts). This module then imports a react-email component from a .tsx file outside of /convex (in /emails/new_share.tsx). This component needs to be provided to the resend SDK.

When I run npx convex dev -v --once, I can see .js files generated from my two files inside of /convex.
I can also see .css files generated for each - these are presumably needed by react-email. I haven't yet investigated whether react-email can build without them.

Regardless, my convex dev command fails because it doesn't want to upload CSS files. I've tried adding 'use node' in the action file, but see the same error.

Any advice or guidance you can give me?

Here's some edited output that shows the error:

➜ npx convex dev -v --once             
Codegen finished.
...
Preparing convex/email.ts
Preparing convex/src/email/new_share.ts
...
Convex's runtime modules:  [
...
  'src/email/new_share.js',
  'email.js',
 ...
  'src/email/new_share.css',
  'email.css'
]
Node.js runtime modules:  []
Remote config will be overwritten with the following changes:
...
Add the following modules:
[+] src/email/new_share.js (327 B, source map 93 B)
[+] email.js (631 B, source map 903 B)
...
[+] src/email/new_share.css (1.6 KB, source map 2.0 KB)
[+] email.css (1.6 KB, source map 2.0 KB)

✖ Error: Unable to push deployment config to https://<redacted>.convex.cloud
400 Bad Request: BadConvexModuleIdentifier: Hit an error while pushing:
src/email/new_share.css is not a valid path to a Convex module. Module path (src/email/new_share.css) has an extension that isn't 'js'.
thin dagger
#

Modules have to be js, I would look into whether react-email can precompile somehow.

#

I'm honestly curious how this works at all, they must be assuming you're using a bundler?

haughty urchin
#

Yes, I tried yesterday but no beans. I've just noticed that the .css files disappear if I don't use their tailwind integration - which is progress.

#

Perhaps that + the render utility

thin dagger
#

Looking through the docs, it doesn't look like they have a great path for Resend + react-email except for Next.js.

haughty urchin
#

With no tailwind, convex still doesn't like the TSX

400 Bad Request: InvalidModules: Hit an error while pushing:
Loading the pushed modules encountered the following
    error:
Failed to analyze src/email/new_share.js: Uncaught SyntaxError: Unexpected token '<'
haughty urchin
thin dagger
#

I would probably reach for that as well, honestly.

silk cloud
haughty urchin
silk cloud
#

What's the file extension of that file?

#

new_share.js

haughty urchin
silk cloud
#

we have esbuild set up to need .tsx/.jsx to allow angle bracket jsx syntax

haughty urchin
silk cloud
#

If this is something you can share I'd love to see, or if you can point me at the guide you're following. We should need to support this a bit better and make a test

#

changing to .tsx may help

#

that's your template or helper file, yeah?

haughty urchin
# silk cloud that's your template or helper file, yeah?

I have an file with the action /convex/email.ts. A file with a module that imports the react-email SDK and the email template /convex/emails/new_share.ts. And the template itself /emails/new_share.tsx

I've just tried changing all these file extensions to .tsx but I'm still seeing an Unexpected token error.

#

Let me take a longer look at the repo/example you shared, see if I can get me head around that

silk cloud
#

there's a tsconfig setting, looks like I set
"jsx": "react"
in the tsconfig.json

#

the one in the convex directory

haughty urchin
# silk cloud If this is something you can share I'd love to see, or if you can point me at th...

I'm following this to install react-email
(https://react.email/docs/getting-started/manual-setup) and this to integrate w/ resend (https://react.email/docs/integrations/resend)

React Email

Create a brand-new folder with packages powered by React Email.

React Email

Learn how to send an email using React Email and the Resend Node.js SDK.

silk cloud
#

Great, thanks

#

curious if changing that tsconfig.json setting changes this

haughty urchin
#

Ok, thanks guys! A combination of:

  • adopting your tsconfig.json
  • moving my email templates from /emails to /convex/emails

means that my convex function has deployed now. Unfortunately I can't test it because resend is down today - but it looks promising and I'm unblocked.

Shame that the CSS files prevent me from using react-email's tailwind integation - but hey, I can live without that

thin dagger
#

Woah they've had a rough couple days

haughty urchin
#

Yeah, 13 hours and counting. Someone is having a really bad day 😦

#

Follow-up: resend is back up and my react-email has sent from a convex action. Thanks for the support and guidance

elfin spade
#

@silk cloud I'm revisiting the issue because I'm still struggling to make this work. I have followed this post and another one at https://discord.com/channels/1019350475847499849/1161498699558559754. Additionally, I have set up a simple example similar to the one you linked from GitHub. I have created my own tsconfig.json in the convex folder, just like in your example. It seems to do the trick regarding building TSX files, but now I am encountering TypeScript errors in my function. For example, in this function:

export const createTemplate = authMutation({
  args: {
    name: v.string(),
  },
  handler: async ({ db, user }, args) => {
    const { name } = args
    return await db.insert('templates', {
      userId: user._id,
      name
    })
  }
})
I Get:
convex/templates.ts:54:21 - error TS7031: Binding element 'db' implicitly has an 'any' type.

handler: async ({ db, user }, args) => {


convex/templates.ts:54:25 - error TS7031: Binding element 'user' implicitly has an 'any' type.

54   handler: async ({ db, user }, args) => {
                       
convex/templates.ts:54:33 - error TS7006: Parameter 'args' implicitly has an 'any' type.

Any ideas?

Discord

Discord is the easiest way to communicate over voice, video, and text. Chat, hang out, and stay close with your friends and communities.

weary crest
#

Where are you importing authMutation from? What is its definition?

elfin spade
#

@weary crest

  1. convex/utils.ts
export const authMutation = customMutation(
  mutation,
  customCtx(async (ctx) => ({ user: await getUserOrThrow(ctx) }))
)

async function getUserOrThrow(ctx: QueryCtx | MutationCtx) {
  const userId = await getUserId(ctx)

  if (!userId) {
    throw new ConvexError('must be logged in')
  }

  const user = await ctx.db
    .query('users')
    .withIndex('by_userId', (q) => q.eq('userId', userId))
    .first()

  if (!user) {
    throw new ConvexError('user not found')
  }

  return user
}
weary crest
#

The error suggests that typescript cannot correctly infer the type for authMutation. I can't see anything wrong with your code. Do you also get the same error in your editor or when running typescript standalone from the command line?

weary crest
#

Yeah

elfin spade
#

I haven't tried yet. I'll need to set up everything again since I moved to a workaround involving Convex calling a Next.js API route to handle the sending.

elfin spade
#

@weary crest Same with running tsc

weary crest
#

Can you share:

  1. The full error details
  2. The full files including imports
  3. Your package.json (one thing worth trying might be to upgrade to latest Convex and convex-helpers version if you're not on them already)

What type do you see when you hover authMutation in your editor?

elfin spade
#

@weary crest Thanks, appreciate the effort to help, but I have fully moved to a solution where Convex is sending an API request to my Next.js backend (#general message), which handles the actual email sending. This also eliminates the CSS files limitation mentioned above.

Discord

Discord is the easiest way to communicate over voice, video, and text. Chat, hang out, and stay close with your friends and communities.