Features
Email Service
Configure and use the email service with Resend and React Email templates.
Overview
Raypx uses Resend as the primary email provider with React Email for templating. The @raypx/email package provides a unified interface for sending emails with pre-built templates.
Features
- Resend Integration: Modern email API with excellent deliverability
- React Email Templates: Build emails with React components
- Nodemailer Fallback: SMTP support for development or alternative providers
- Preview Server: Local development server for testing emails
- Type-Safe: Full TypeScript support for all email operations
Configuration
Environment Variables
Add the following to your .env file:
# ===== Email Configuration =====
# Primary: Resend (recommended for production)
RESEND_API_KEY=re_xxxxxxxxxxxxx
RESEND_FROM=noreply@yourdomain.com
# Optional: Nodemailer (for SMTP fallback or development)
SMTP_HOST=smtp.example.com
SMTP_PORT=587
SMTP_USER=your-username
SMTP_PASS=your-password
SMTP_FROM=noreply@yourdomain.comGetting Your Resend API Key
- Sign up for a Resend account
- Verify your domain in the dashboard
- Go to API Keys and create a new key
- Copy the API key to your
.envfile
Quick Start
Sending an Email
import { sendEmail } from "@raypx/email";
import { WelcomeEmail } from "@raypx/email/templates";
await sendEmail({
to: "user@example.com",
subject: "Welcome to Raypx!",
react: WelcomeEmail({ name: "John" }),
});Using Pre-built Templates
The @raypx/email package includes several pre-built templates:
import { sendEmail } from "@raypx/email";
import {
WelcomeEmail,
PasswordResetEmail,
MagicLinkEmail,
VerificationEmail,
} from "@raypx/email/templates";
// Welcome email
await sendEmail({
to: "user@example.com",
subject: "Welcome!",
react: WelcomeEmail({
name: "John",
loginUrl: "https://yourdomain.com/login",
}),
});
// Password reset
await sendEmail({
to: "user@example.com",
subject: "Reset Your Password",
react: PasswordResetEmail({
name: "John",
resetUrl: "https://yourdomain.com/reset?token=xxx",
}),
});
// Magic link
await sendEmail({
to: "user@example.com",
subject: "Sign in to Raypx",
react: MagicLinkEmail({
name: "John",
magicLinkUrl: "https://yourdomain.com/auth/magic-link?token=xxx",
}),
});Email Preview Server
During development, use the email preview server to test emails without sending them.
Start Preview Server
pnpm dev:email
# or
pnpm --filter @raypx/email devThe preview server runs at http://localhost:3003 by default.
Preview Features
- Live Preview: See emails rendered in real-time
- Hot Reload: Changes to templates update instantly
- Multiple Views: Desktop, mobile, and plain text previews
- Send Test: Send test emails to yourself
Creating Custom Templates
Template Structure
Create templates using React Email components:
// packages/email/templates/custom-email.tsx
import {
Body,
Container,
Head,
Heading,
Html,
Link,
Paragraph,
Text,
} from "@react-email/components";
interface CustomEmailProps {
name: string;
actionUrl: string;
}
export function CustomEmail({ name, actionUrl }: CustomEmailProps) {
return (
<Html>
<Head />
<Body style={main}>
<Container style={container}>
<Heading style={h1}>Hello {name}!</Heading>
<Paragraph style={paragraph}>
This is a custom email template.
</Paragraph>
<Link href={actionUrl} style={link}>
Click here
</Link>
<Text style={footer}>
© {new Date().getFullYear()} Raypx. All rights reserved.
</Text>
</Container>
</Body>
</Html>
);
}
const main = {
backgroundColor: "#ffffff",
fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",
};
const container = {
margin: "0 auto",
padding: "20px 0 48px",
maxWidth: "580px",
};
const h1 = {
color: "#1a1a1a",
fontSize: "24px",
fontWeight: "600" as const,
margin: "0 0 20px",
};
const paragraph = {
color: "#374151",
fontSize: "16px",
lineHeight: "24px",
margin: "0 0 20px",
};
const link = {
color: "#2563eb",
textDecoration: "underline",
};
const footer = {
color: "#8898aa",
fontSize: "12px",
marginTop: "24px",
};
export default CustomEmail;Export Template
Add your template to the package exports:
// packages/email/templates/index.ts
export { CustomEmail } from "./custom-email";Available Templates
| Template | Description | Props |
|---|---|---|
WelcomeEmail | Welcome new users | name, loginUrl |
PasswordResetEmail | Password reset link | name, resetUrl |
MagicLinkEmail | Magic link authentication | name, magicLinkUrl |
VerificationEmail | Email verification | name, verificationUrl |
Integration with Auth
The email service integrates with Better Auth for authentication emails:
// packages/auth/src/server/auth.ts
import { sendEmail } from "@raypx/email";
import { MagicLinkEmail, VerificationEmail } from "@raypx/email/templates";
export const auth = betterAuth({
// ... other config
emailVerification: {
sendVerificationEmail: async ({ user, url }) => {
await sendEmail({
to: user.email,
subject: "Verify your email",
react: VerificationEmail({
name: user.name,
verificationUrl: url,
}),
});
},
},
magicLink: {
sendMagicLink: async ({ email, url }) => {
await sendEmail({
to: email,
subject: "Sign in to Raypx",
react: MagicLinkEmail({
name: email,
magicLinkUrl: url,
}),
});
},
},
});Best Practices
Email Content
- Clear Subject Lines: Keep subjects concise and descriptive
- Personalization: Use the recipient's name when available
- Call to Action: Include clear, prominent action buttons
- Plain Text: Always provide a plain text version
- Unsubscribe: Include unsubscribe links for marketing emails
Deliverability
- Verify Domain: Complete domain verification in Resend
- SPF/DKIM/DMARC: Configure DNS records properly
- Warm Up IP: Start with low volumes and increase gradually
- Monitor Bounces: Track and handle bounced emails
- Avoid Spam Triggers: Don't use spammy words or excessive caps
Development
- Use Preview Server: Test emails locally before sending
- Test Multiple Clients: Check rendering in different email clients
- Responsive Design: Ensure emails work on mobile devices
- Keep Templates Simple: Complex layouts may break in some clients
Troubleshooting
Email Not Sending
- Check API Key: Verify
RESEND_API_KEYis correct - Check From Address: Must use a verified domain
- Check Logs: Look for error messages in server logs
- Test Connection: Use Resend dashboard to send test email
Emails Going to Spam
- Verify Domain: Complete domain verification
- Check DNS Records: Ensure SPF, DKIM, DMARC are configured
- Monitor Reputation: Check sender reputation in Resend dashboard
- Review Content: Avoid spam trigger words
Template Not Rendering
- Check Imports: Ensure all components are imported correctly
- Check Props: Verify all required props are provided
- Use Preview: Test in email preview server
- Check Console: Look for React errors