Contact form: reCAPTCHA and EmailJS
The contact UI is in src/components/contact/EmailSection.jsx. It posts JSON to /api/email/send by default. You can wire EmailJS in the browser (emailjs.send from @emailjs/browser) or implement the API route on the server. Pick one approach.
Websites
| Service | URL | What you do there |
| Google reCAPTCHA (v2) | https://www.google.com/recaptcha/admin | Register your site, choose v2 "I'm not a robot", add localhost and your production domain, copy Site key (and Secret key if verifying server-side). |
| EmailJS | https://www.emailjs.com | Sign up, connect an Email Service (Gmail, Outlook, etc.), create an Email Template with fields matching your form, copy Public Key, Service ID, and Template ID. |
Environment variables
reCAPTCHA (site key in the browser):
NEXT_PUBLIC_RECAPTCHA_SITE_KEY=your_site_keyOptional server verification (only if your /api/email/send route checks the token with Google):
RECAPTCHA_SECRET_KEY=your_secret_keyDo not prefix the secret with NEXT_PUBLIC_.
Without NEXT_PUBLIC_RECAPTCHA_SITE_KEY, the form shows an error state in development.
EmailJS wiring
- In the EmailJS dashboard, open Account > General for your Public Key.
- Under Email Services, note the Service ID per connected provider.
- Under Email Templates, create variables matching your form (e.g.
name,email,subject,message) and note the Template ID. - In
EmailSection.jsx, callemailjs.init(publicKey)andemailjs.send(serviceId, templateId, templateParams)after reCAPTCHA succeeds.
Security: Use EmailJS allowed domains / restrictions where available. Do not expose private keys in NEXT_PUBLIC_* variables.
Optional server route
Implement src/app/api/email/send/route.js to send mail via EmailJS REST, Resend, SendGrid, etc. Validate input and verify reCAPTCHA on the server if you use RECAPTCHA_SECRET_KEY.