Overview
aSaaSin renders transactional emails with React Email and sends them through Resend. We mirror app colors via a custom <Tailwind />
wrapper and load a web font so emails match site styling.
Elements & layout
Build emails from small blocks; here are the pieces we use and why:
Html
,Head
,Body
: email document shell; always include these for consistent rendering.Preview
: short preview line shown by clients next to the subject.Container
: fixed-width content area; center and add padding.Section
: stackable layout rows; use for spacing and grouping.Heading
,Text
,Link
,Img
,Hr
,Button
: basic content primitives with email-safe attributes.<Tailwind />
: wraps children and provides a minimal Tailwind config (colors only) so you can use the same tokens as the app.<Font />
: declares a web font once; clients that support remote fonts will use it, others fall back.
Share Tailwind tokens
Extend React Email’s Tailwind config with the app’s HexColors
so classes like bg-secondary-dark
and text-primary-light
work the same as in the UI.
// emails/tailwind.tsx — reuse app colors inside emails
import { Tailwind as ReactEmailTailwind, TailwindProps } from '@react-email/components';
import * as React from 'react';
import { HexColors } from '@/constants/colors';
const Tailwind: React.FC<TailwindProps> = (props) => (
<ReactEmailTailwind
{...props}
config={{
theme: {
extend: {
colors: { ...HexColors },
},
},
}}
/>
);
export default Tailwind;
Font setup
Declare a web font once and reuse it across templates; React Email injects the correct @font-face
rules.
// emails/font.tsx — declare a web font for supported clients
import { Font as ReactEmailFont } from '@react-email/components';
import * as React from 'react';
const Font: React.FC = () => (
<ReactEmailFont
fontFamily="Bricolage Grotesque"
fallbackFontFamily="sans-serif"
webFont={{
url: 'https://fonts.gstatic.com/s/bricolagegrotesque/v7/3y9K6as8bTXq_nANBjzKo3IeZx8z6up5BeSl9D4dj_x9PpZBMlGIInHWVyNJ.woff2',
format: 'woff2',
}}
fontWeight="400 700"
/>
);
export default Font;
Many clients (Apple Mail/iOS) support remote fonts; Gmail web often does not. Always include a solid fallback stack.
Config Google Font
Get the .woff2
URL from Google Fonts so you can supply it to <Font />
:
- Open the font on Google Fonts (e.g., Bricolage Grotesque) and click Get font / Select styles.
- Under Use on the web, choose link, select weights you need (e.g., 400, 700), and open the generated
fonts.googleapis.com/css2
URL in a new tab. - In the returned CSS, copy the
https://fonts.gstatic.com/... .woff2
URL for the latin subset (smallest) and paste it intowebFont.url
. - If you add italics or more weights later, regenerate the CSS and update the URL.
Simple example
Here’s a minimal template using our layout pieces and shared tokens.
// emails/Example.tsx — minimal skeleton
import { Html, Head, Preview, Body, Container, Section, Heading, Text } from '@react-email/components';
import Tailwind from '@/emails/tailwind';
import Font from '@/emails/font';
export default function ExampleEmail() {
return (
<Html>
<Head><Font /></Head>
<Preview>Short preview text</Preview>
<Tailwind>
<Body className="m-auto bg-secondary-dark px-2 font-sans">
<Container className="mx-auto my-[40px] max-w-[465px] rounded-xl border border-neutral p-[20px]">
<Section className="text-center">
<Heading className="mb-3 text-[22px] font-bold text-primary-light">Hello!</Heading>
<Text className="text-[14px] leading-[24px] text-primary-light">
This is a minimal React Email template styled with aSaaSin tokens.
</Text>
</Section>
</Container>
</Body>
</Tailwind>
</Html>
);
}
Send with Resend
We send from the server using Resend—simple API, React component payloads, and reliable infrastructure.
import { Resend } from 'resend';
import ExampleEmail from '@/emails/Example';
const resend = new Resend(process.env.RESEND_API_KEY!);
export async function sendExampleEmail(to: string) {
const { data, error } = await resend.emails.send({
from: 'aSaaSin <noreply@your-domain.tld>',
to,
subject: 'Hello from aSaaSin',
react: <ExampleEmail />,
});
return error
? { success: false, error: error.message }
: { success: true, id: data?.id };
}
Tips
- Keep templates small and linear; prefer simple layout stacks (
Section
,Container
). - Snapshot-test rendered HTML to catch regressions.
- Reuse app tokens (
HexColors
) so emails and site stay visually consistent.