At Cerebral Valley we use Supertokens for authentication into our platform.
Supertokens comes with a default email template / design that is sent to users upon account creation, email confirmation, and other actions.
We wanted to customize emails sent out from Supertokens to our users to keep the brand aesthetic, so we used Resend and React Email to do so.
I wrote up this post to give step by step instructions of how to combine the three technologies and showcase their simplicity.
Pre-requisites
Your project will need to be using Supertokens as the method of authentication.
In this walkthrough, I am working out of a Typescript project with an Express backend.
Resend setup
First, you will need to create a Resend account. Resend is a new platform to send emails programmatically. Think Sendgrid but modern and easier to use.
Sign up and go through the onboarding flow to get an API key. By default, the first key that is created is called "Onboarding"
Add your API key to your .env
file, something like
RESEND_API_KEY="<your_api_key>"
Then, add the domain you want to send your emails from.
You will have to add a few records to your domain which Resend will walk you through.
Next, create a file in your project called smpt.ts
with the following contents
const smtpSettings = {
host: 'smtp.resend.com',
authUsername: 'resend',
password: process.env.RESEND_API_KEY,
port: 465,
from: {
name: '<your_email_sender_name>',
email: '<your_email_account>',
},
secure: true,
};
export { smtpSettings };
React Email setup
React Email is a library built by the founder of Resend. Since emails support HTML, the library allows you to customize emails with React components and then compiles them down to HTML before sending.
To install React Email, run
yarn add react @react-email/components @react-email/render
Create your a file named Email.tsx
for your React Email components. The file contents would be something like this
import * as React from 'react';
import { render } from '@react-email/render';
import {
Body,
Button,
Container,
Head,
Heading,
Hr,
Html,
Img,
Link,
Preview,
Section,
} from '@react-email/components';
const emailSubject = 'Email Subject';
const EmailHtml = (content: string): string => {
return render(<Email content={content} />);
};
// Component
interface EmailProps {
content: string;
}
function Email(props: EmailProps): JSX.Element {
const { content } = props;
return (
<Html>
<Head />
<Preview>{'What the user sees in the preview'}</Preview>
<Body style={main}>
<Container style={container}>
<Img
src={`https://yourlogo.com/logo.png`}
width="42"
height="42"
alt="Logo"
style={logo}
/>
<Heading style={heading}>Click the button below</Heading>
<Section style={buttonContainer}>
<Button style={button} href={content}>
My button
</Button>
</Section>
</Container>
</Body>
</Html>
);
}
// Styling
const logo = {
borderRadius: 21,
width: 42,
height: 42,
};
const main = {
backgroundColor: '#090909',
fontFamily:
'-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif',
// ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"
};
const container = {
margin: '0 auto',
padding: '20px 0 48px',
maxWidth: '560px',
};
const heading = {
fontSize: '24px',
letterSpacing: '-0.5px',
lineHeight: '1.3',
fontWeight: '400',
color: '#fff',
padding: '17px 0 0',
};
const paragraph = {
margin: '0 0 15px',
fontSize: '15px',
lineHeight: '1.4',
color: '#3c4149',
};
const buttonContainer = {
padding: '27px 0 27px',
};
const button = {
backgroundColor: '#fff',
borderRadius: '3px',
fontWeight: '600',
color: '#000',
fontSize: '15px',
textDecoration: 'none',
textAlign: 'center' as const,
display: 'block',
padding: '11px 23px',
};
const reportLink = {
fontSize: '14px',
color: '#b4becc',
};
const hr = {
borderColor: '#dfe1e4',
margin: '42px 0 26px',
};
export { EmailHtml, emailSubject };
Note that the above code is for a showing a link in the email. Your content may be different.
Supertokens Config
Supertokens allows you to use your own domain / SMTP server (link to docs). We take advantage of this method to plug in Resend and the created React component.
In your Supertokens config, override the smtp settings as described in their docs here.
Don't forget to import your smtpSettings and Email component.
Your Supertokens config would look something like this
import supertokens from "supertokens-node";
import Passwordless from "supertokens-node/recipe/passwordless";
import Session from "supertokens-node/recipe/session";
import { SMTPService } from "supertokens-node/recipe/passwordless/emaildelivery";
import EmailVerification from "supertokens-node/recipe/emailverification"
import { SMTPService as EmailVerificationSMTPService } from "supertokens-node/recipe/emailverification/emaildelivery";
import { smtpSettings } from './smtp';
import { EmailHtml, emailSubject } from './Email';
supertokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "..."
},
recipeList: [
Passwordless.init({
emailDelivery: {
service: new SMTPService({
smtpSettings,
override: (originalImplementation): any => {
return {
...originalImplementation,
getContent: async function (input): Promise<any> {
const {
isFirstFactor,
codeLifetime, // amount of time the code is alive for (in MS)
email,
urlWithLinkCode, // magic link
} = input;
if (isFirstFactor) {
return {
body: EmailHtml(urlWithLinkCode),
isHtml: true,
subject: emailSubject,
toEmail: email,
};
} else {
return {
body: EmailHtml(urlWithLinkCode),
isHtml: true,
subject: emailSubject,
toEmail: email,
};
}
},
};
},
}),
},
}),
Session.init()
]
});
In the config above, we override the email delivery service with our own definition of the SMPTService
, where we set the previously defined smptSettings
and a new getContent
function definition. In the new getContent
, we get the defined React Component as the body of the email. The component is compiled into HTML, so we can use it in the email.
With those changes, you can start the server and run through the authentication flow. When you receive the email from Supertokens, you should see your new component design as the body of the email.
Wrapping up
If you're using Supertokens for your authentication, I highly recommend using Resend and React Email to customize your emails. It's very simple to setup and a pleasant developer experience.
If you have any questions, send me a DM in our community Slack.
Check out what we're building at Cerebral Valley.
Top comments (0)