Skip to main content

Contact Form Setup Guide

This document explains the custom contact form implementation using Resend for email delivery.

Overview

The contact form on /contact-me has been replaced with a custom React form that uses Resend to send emails. This provides a better user experience and more control over the form submission process.

Features

  • ✅ Custom React form with validation
  • ✅ Responsive design matching the site's monochrome theme
  • ✅ Two-email system:
  • ✅ Loading states and error handling
  • ✅ Success message with auto-dismiss
  • ✅ Dark mode support

Form Fields

Required Fields:

  • Name
  • Email
  • Subject
  • Message

Optional Fields:

  • Company Name
  • Phone Number

Architecture

Frontend Component

  • Location: /src/components/ContactForm/
  • Files:
    • index.jsx - React component with form logic
    • styles.module.css - CSS module for styling

Backend API

  • Location: /functions/api/contact.js
  • Type: Cloudflare Pages Function
  • Method: POST only
  • CORS: Enabled for cross-origin requests

Email Service

  • Provider: Resend
  • Package: resend@6.2.2
  • Authentication: API key stored as Cloudflare secret

Setup Instructions

1. Get Resend API Key

  1. Sign up at resend.com
  2. Navigate to API Keys
  3. Create a new API key
  4. Copy the API key (starts with re_)

2. Verify Domain in Resend

Option A: Verify Root Domain (cameronrohn.com)

  1. Go to Resend Domains
  2. Click "Add Domain"
  3. Enter: cameronrohn.com
  4. Resend will provide DNS records (SPF and DKIM)

Option B: Use Subdomain (Recommended)

For better email deliverability, use a subdomain:

  1. Go to Resend Domains
  2. Click "Add Domain"
  3. Enter: mail.cameronrohn.com or send.cameronrohn.com
  4. Resend will provide DNS records

3. Configure DNS Records (Cloudflare)

  1. Go to Cloudflare Dashboard
  2. Select domain: cameronrohn.com
  3. Navigate to DNSRecords
  4. Add the records provided by Resend:

SPF Record:

  • Type: TXT
  • Name: @ (or subdomain name if using subdomain)
  • Content: v=spf1 include:_spf.resend.com ~all
  • TTL: Auto

DKIM Record:

  • Type: TXT
  • Name: (e.g., resend._domainkey)
  • Content: (long cryptographic key from Resend)
  • TTL: Auto
  1. Wait 5-10 minutes for DNS propagation
  2. Return to Resend and click "Verify"

4. Set Cloudflare Secret

For production deployment, set the API key as a Cloudflare secret:

wrangler secret put RESEND_API_KEY

When prompted, paste your Resend API key.

5. Local Development (Optional)

For local testing with actual email sending:

  1. Create .env.local file:

    RESEND_API_KEY=re_your_api_key_here
  2. Note: Local development uses Docusaurus dev server which doesn't support Cloudflare Functions. To test the API endpoint locally, you'll need to:

    • Deploy to Cloudflare Pages preview environment, OR
    • Use wrangler pages dev for local function testing

Email Configuration

Update "From" Address

If using a subdomain, update the from field in /functions/api/contact.js:

// Change from:
from: 'Cameron Rohn - Contact <noreply@cameronrohn.com>',

// To:
from: 'Cameron Rohn - Contact <noreply@mail.cameronrohn.com>',

Customize Email Templates

The HTML email templates are located in /functions/api/contact.js:

You can customize:

  • Colors and styling
  • Text content
  • Logo/branding
  • Layout

Deployment

Build and Deploy

# Build the site
yarn build

# Deploy to Cloudflare Pages
wrangler deploy

The build process will:

  1. Generate content index
  2. Build Docusaurus static site
  3. Build Cloudflare Functions

Verify Deployment

  1. Visit: https://cameronrohn.com/contact-me
  2. Fill out the form
  3. Submit and verify:
    • Success message appears
    • Email received at cameron@cameronrohn.com
    • Confirmation email received at submitted address

Troubleshooting

Form submits but no emails sent

Check 1: Domain Verification

  • Go to Resend Domains
  • Ensure domain shows "Verified" status
  • If not verified, check DNS records in Cloudflare

Check 2: API Key

  • Verify secret is set: wrangler secret list
  • If not listed, run: wrangler secret put RESEND_API_KEY

Check 3: Cloudflare Logs

wrangler tail

Submit the form and check for errors in the logs.

Check 4: Resend Dashboard

  • Go to Resend Emails
  • Check for failed delivery attempts
  • Review error messages

Form shows error message

Check Network Tab:

  • Open browser DevTools → Network tab
  • Submit form
  • Look for /api/contact request
  • Check response status and error message

Common Issues:

  • 400: Missing required fields → Check form validation
  • 401: Invalid API key → Reset Cloudflare secret
  • 500: Server error → Check wrangler tail logs

Emails go to spam

Solutions:

  1. Verify SPF and DKIM records are correct
  2. Use subdomain instead of root domain
  3. Warm up the domain by sending a few test emails
  4. Check Resend's deliverability guide

CORS errors

If you see CORS errors in the browser console:

  • Check that /functions/api/contact.js has correct CORS headers
  • Verify the API endpoint is being called at /api/contact
  • Ensure Cloudflare Functions are deployed

Testing Checklist

  • Domain verified in Resend dashboard
  • DNS records added to Cloudflare
  • Cloudflare secret RESEND_API_KEY set
  • Site deployed to Cloudflare Pages
  • Form loads on https://cameronrohn.com/contact-me
  • All fields visible and functional
  • Required field validation works
  • Form submission shows loading state
  • Success message appears after submission
  • Notification email received at cameron@cameronrohn.com
  • Confirmation email received at submitted address
  • Reply-to address is set correctly
  • Email formatting looks good in Gmail/Outlook
  • Dark mode styling works correctly
  • Mobile responsive design works

Security Notes

  • ✅ API key stored as Cloudflare secret (not in code)
  • ✅ CORS headers configured for security
  • ✅ Input validation on both frontend and backend
  • ✅ Email validation using regex
  • ✅ No API key in .env.example (uses placeholder)
  • ✅ Sanitized HTML output to prevent injection

File Structure

website-docusaurus01/
├── src/
│ ├── components/
│ │ └── ContactForm/
│ │ ├── index.jsx # Form component
│ │ └── styles.module.css # Styles
│ └── pages/
│ └── contact-me.mdx # Contact page
├── functions/
│ └── api/
│ └── contact.js # Cloudflare Function
├── .env.example # Environment template
├── package.json # Dependencies (includes resend)
└── docs/
└── CONTACT_FORM_SETUP.md # This file

Resources

Support

For issues or questions:

  1. Check this guide first
  2. Review Resend docs
  3. Check Cloudflare logs: wrangler tail
  4. Review Resend dashboard for delivery logs