Resend is the email service provider used in PC Fix for sending transactional emails including order confirmations, status updates, password resets, and customer notifications.
Overview
PC Fix uses Resend to send:
Order Updates : Status changes, shipping notifications
Customer Support : Contact confirmations, inquiry replies
Authentication : Welcome emails, password resets
Marketing : Abandoned cart reminders, stock alerts, price drops
Configuration
Create a Resend Account
Sign up for an account at resend.com . The free tier includes 100 emails per day.
Generate an API Key
Go to API Keys in your Resend dashboard and create a new API key with send permissions.
Verify Your Domain (Optional)
For production use, verify your sending domain in Resend to improve deliverability and remove “via resend.com” from emails.
Set Environment Variables
Add these variables to your .env file in the packages/api directory:
Keep your RESEND_API_KEY secret. Never expose it in client-side code or commit it to version control.
Email Service Implementation
The EmailService class is located at packages/api/src/shared/services/EmailService.ts:
import { Resend } from 'resend' ;
export class EmailService {
private resend : Resend ;
private frontendUrl : string ;
constructor () {
this . resend = new Resend ( process . env . RESEND_API_KEY );
this . frontendUrl = process . env . FRONTEND_URL || 'http://localhost:4321' ;
}
async sendEmail ( to : string , subject : string , htmlContent : string ) {
try {
const fromEmail = process . env . EMAIL_FROM || 'PCFIX <[email protected] >' ;
const replyToAddress = process . env . REPLY_TO || '[email protected] ' ;
const { data , error } = await this . resend . emails . send ({
from: fromEmail ,
replyTo: replyToAddress ,
to ,
subject ,
html: htmlContent ,
});
if ( error ) {
console . error ( 'Error sending email (Resend):' , error );
return false ;
}
return true ;
} catch ( error ) {
console . error ( 'Unexpected error sending email:' , error );
return false ;
}
}
}
Available Email Templates
The EmailService provides pre-built templates for common scenarios:
Order & Payment Emails
Status Update
Receipt Notification
Shipment Created
await emailService . sendStatusUpdate (
userEmail ,
saleId ,
'APROBADO' ,
'ENVIO' ,
'TR123456789'
);
Authentication Emails
Welcome Email
Password Reset
await emailService . sendWelcomeEmail (
email ,
name
);
Customer Support
Contact Confirmation
New Inquiry Notification
Reply Notification
await emailService . sendContactConfirmationEmail (
userEmail ,
userName
);
Marketing Emails
Abandoned Cart
Stock Alert
Price Drop
await emailService . sendAbandonedCartEmail (
userEmail ,
userName ,
products
);
Email Template Structure
All email templates follow a consistent HTML structure:
< div style = "font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: #1f2937; max-width: 600px; margin: 0 auto;
background-color: #ffffff; border: 1px solid #e5e7eb;
border-radius: 12px; overflow: hidden;" >
<!-- Header -->
< div style = "background-color: #111827; padding: 25px; text-align: center;" >
< h1 style = "color: #ffffff; margin: 0; font-size: 24px; font-weight: 800;" >
PC FIX
</ h1 >
</ div >
<!-- Content -->
< div style = "padding: 30px;" >
<!-- Email content here -->
</ div >
<!-- Footer -->
< div style = "background-color: #f9fafb; padding: 20px; text-align: center;
border-top: 1px solid #e5e7eb; font-size: 12px; color: #9ca3af;" >
< p style = "margin: 0;" > PC FIX - Experiencia en Hardware </ p >
</ div >
</ div >
Email templates use inline CSS for maximum compatibility across email clients.
Usage Example
Here’s how to use the email service in your controllers:
import { EmailService } from '@/shared/services/EmailService' ;
const emailService = new EmailService ();
export const updateSaleStatus = async ( req : Request , res : Response ) => {
const { id } = req . params ;
const { estado , tipoEntrega , codigoSeguimiento } = req . body ;
// Update sale in database
const sale = await prisma . venta . update ({
where: { id: Number ( id ) },
data: { estado , codigoSeguimiento },
});
// Send status update email
if ( sale . cliente ?. email ) {
await emailService . sendStatusUpdate (
sale . cliente . email ,
sale . id ,
estado ,
tipoEntrega ,
codigoSeguimiento
);
}
res . json ({ success: true , sale });
};
Order Status Messages
The sendStatusUpdate method automatically generates appropriate messages for each status:
Status Icon Message APROBADO✅ Your payment has been approved! We’re preparing your order. PENDIENTE_APROBACION⏳ We received your receipt. Our team is verifying the payment. RECHAZADO❌ We couldn’t verify your payment. Please check the receipt. CANCELADO🚫 Your order has been cancelled. ENVIADO (Pickup)🏪 Your order is ready for pickup at our store! ENVIADO (Delivery)🚚 Your order is on its way! Track it with code: . ENTREGADO🚀 Thank you for trusting PC FIX! Enjoy your hardware!
Environment Variables
Your Resend API key from the dashboard
The sender email address and name
Reply-to email address for customer responses
Admin email for receiving notifications about new inquiries and receipts
FRONTEND_URL
string
default: "http://localhost:4321"
Frontend URL for generating links in emails
Testing Emails
Resend provides a test mode for development:
// Test email in development
if ( process . env . NODE_ENV === 'development' ) {
console . log ( '📧 Email would be sent to:' , to );
console . log ( '📝 Subject:' , subject );
}
Deliverability Tips
Add SPF, DKIM, and DMARC records to your domain to improve deliverability and remove “via resend.com” from emails.
Use Professional Sender Names
Use a recognizable sender name like “PCFIX” rather than just an email address.
Include Unsubscribe Links
For marketing emails, always include an unsubscribe link to comply with regulations.
Check your Resend dashboard regularly for bounced emails and remove invalid addresses.
Error Handling
The email service includes error handling:
if ( error ) {
console . error ( '🔥 Error sending email (Resend):' , error );
return false ; // Email failed to send
}
return true ; // Email sent successfully
Always check the return value when sending critical emails:
const sent = await emailService . sendStatusUpdate ( ... );
if ( ! sent ) {
// Handle email failure (log, retry, notify admin)
console . error ( 'Failed to send status update email' );
}
Rate Limits
Free Tier : 100 emails per day
Paid Plans : Higher limits based on plan
Implement rate limiting or queueing for high-volume scenarios to avoid hitting API limits.