Skip to content

Commit b7e509d

Browse files
committed
feat(contact): implement EmailJS for reliable email sending
- Replace mailto links with EmailJS service for cross-browser compatibility - Add professional email template with HTML formatting - Implement async email sending with proper error handling - Remove browser detection and fallback modals (no longer needed) - Add comprehensive EmailJS setup guide - Ensure reliable email delivery across all browsers and devices - Free tier supports 200 emails per month (perfect for portfolio)
1 parent 6ae1d98 commit b7e509d

4 files changed

Lines changed: 196 additions & 206 deletions

File tree

EMAILJS_SETUP.md

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
# EmailJS Setup Guide
2+
3+
## 🚀 What is EmailJS?
4+
5+
EmailJS is a service that allows you to send emails directly from your frontend JavaScript code without needing a backend server. It's perfect for portfolio websites and works reliably across all browsers and devices.
6+
7+
## 📋 Setup Steps
8+
9+
### 1. Create EmailJS Account
10+
1. Go to [https://www.emailjs.com/](https://www.emailjs.com/)
11+
2. Sign up for a free account
12+
3. Verify your email address
13+
14+
### 2. Add Email Service
15+
1. In your EmailJS dashboard, go to "Email Services"
16+
2. Click "Add New Service"
17+
3. Choose "Gmail" (or your preferred email provider)
18+
4. Connect your Gmail account (davidsyagustin@gmail.com)
19+
5. Note down the **Service ID** (e.g., `service_abc123`)
20+
21+
### 3. Create Email Template
22+
1. Go to "Email Templates"
23+
2. Click "Create New Template"
24+
3. Use this template:
25+
26+
**Subject:**
27+
```
28+
Portfolio Contact from {{from_name}}
29+
```
30+
31+
**Email Content:**
32+
```html
33+
<!DOCTYPE html>
34+
<html>
35+
<head>
36+
<title>Portfolio Contact</title>
37+
</head>
38+
<body style="font-family: Arial, sans-serif; line-height: 1.6; color: #333;">
39+
<div style="max-width: 600px; margin: 0 auto; padding: 20px;">
40+
<h2 style="color: #2563eb;">New Portfolio Contact</h2>
41+
42+
<div style="background-color: #f8fafc; padding: 20px; border-radius: 8px; margin: 20px 0;">
43+
<h3 style="margin-top: 0; color: #1e40af;">Contact Information</h3>
44+
<p><strong>Name:</strong> {{from_name}}</p>
45+
<p><strong>Email:</strong> {{from_email}}</p>
46+
</div>
47+
48+
<div style="background-color: #fefefe; padding: 20px; border-left: 4px solid #2563eb; margin: 20px 0;">
49+
<h3 style="margin-top: 0; color: #1e40af;">Message</h3>
50+
<p style="white-space: pre-wrap;">{{message}}</p>
51+
</div>
52+
53+
<div style="margin-top: 30px; padding-top: 20px; border-top: 1px solid #e5e7eb; font-size: 14px; color: #6b7280;">
54+
<p>This message was sent from your portfolio contact form at <a href="https://davidagustin.github.io" style="color: #2563eb;">https://davidagustin.github.io</a></p>
55+
</div>
56+
</div>
57+
</body>
58+
</html>
59+
```
60+
61+
4. Save the template and note down the **Template ID** (e.g., `template_xyz789`)
62+
63+
### 4. Get Your Public Key
64+
1. Go to "Account" → "API Keys"
65+
2. Copy your **Public Key** (e.g., `user_abc123def456`)
66+
67+
### 5. Update Your Code
68+
Replace the placeholder values in `src/components/Contact.tsx`:
69+
70+
```typescript
71+
// Replace these values with your actual EmailJS credentials
72+
emailjs.init("YOUR_PUBLIC_KEY"); // Your public key
73+
74+
const result = await emailjs.send(
75+
'YOUR_SERVICE_ID', // Your service ID
76+
'YOUR_TEMPLATE_ID', // Your template ID
77+
templateParams,
78+
'YOUR_PUBLIC_KEY' // Your public key
79+
);
80+
```
81+
82+
## 🔧 Configuration Example
83+
84+
After setup, your code should look like this:
85+
86+
```typescript
87+
// Initialize EmailJS
88+
useEffect(() => {
89+
emailjs.init("user_abc123def456"); // Your actual public key
90+
}, []);
91+
92+
// Send email
93+
const result = await emailjs.send(
94+
'service_abc123', // Your actual service ID
95+
'template_xyz789', // Your actual template ID
96+
templateParams,
97+
'user_abc123def456' // Your actual public key
98+
);
99+
```
100+
101+
## ✅ Benefits of EmailJS
102+
103+
- **No Backend Required**: Works entirely from frontend
104+
- **Cross-Browser Compatible**: Works on Chrome, Firefox, Safari, Edge
105+
- **Mobile Friendly**: Works on all mobile devices
106+
- **Professional Emails**: Beautiful HTML templates
107+
- **Reliable Delivery**: Emails go directly to your inbox
108+
- **Free Tier**: 200 emails per month (perfect for portfolio)
109+
110+
## 🎯 What You'll Get
111+
112+
When someone submits your contact form:
113+
1. **Instant Delivery**: Email arrives in your inbox immediately
114+
2. **Professional Format**: Beautiful HTML email with contact details
115+
3. **No Browser Issues**: Works consistently across all platforms
116+
4. **User Feedback**: Clear success/error messages
117+
5. **Form Reset**: Form clears after successful submission
118+
119+
## 🔒 Security Notes
120+
121+
- Your public key is safe to expose in frontend code
122+
- EmailJS handles authentication securely
123+
- No sensitive credentials are exposed
124+
- Rate limiting prevents spam
125+
126+
## 🚀 Next Steps
127+
128+
1. Follow the setup steps above
129+
2. Replace the placeholder values in your code
130+
3. Test the form on your local development server
131+
4. Deploy to GitHub Pages
132+
5. Test on live site
133+
134+
Your contact form will now work reliably across all browsers and devices! 🎉

package-lock.json

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,26 +15,31 @@
1515
"check": "biome check ."
1616
},
1717
"dependencies": {
18+
"@emailjs/browser": "^4.4.1",
19+
"framer-motion": "^10.16.0",
1820
"react": "^18.2.0",
1921
"react-dom": "^18.2.0",
20-
"react-scripts": "5.0.1",
22+
"react-icons": "^4.10.0",
2123
"react-router-dom": "^6.8.0",
22-
"framer-motion": "^10.16.0",
23-
"react-icons": "^4.10.0"
24+
"react-scripts": "5.0.1"
2425
},
2526
"devDependencies": {
27+
"@biomejs/biome": "^1.5.0",
28+
"@types/node": "^20.0.0",
2629
"@types/react": "^18.2.0",
2730
"@types/react-dom": "^18.2.0",
28-
"@types/node": "^20.0.0",
29-
"typescript": "^4.9.5",
30-
"tailwindcss": "^3.3.0",
3131
"autoprefixer": "^10.4.0",
32+
"gh-pages": "^5.0.0",
3233
"postcss": "^8.4.0",
33-
"@biomejs/biome": "^1.5.0",
34-
"gh-pages": "^5.0.0"
34+
"tailwindcss": "^3.3.0",
35+
"typescript": "^4.9.5"
3536
},
3637
"browserslist": {
37-
"production": [">0.2%", "not dead", "not op_mini all"],
38+
"production": [
39+
">0.2%",
40+
"not dead",
41+
"not op_mini all"
42+
],
3843
"development": [
3944
"last 1 chrome version",
4045
"last 1 firefox version",

0 commit comments

Comments
 (0)