Progressive Enhancement and Form Actions
In React Router v7 and Remix, form submissions are handled on the server via action functions. This guarantees that email submissions succeed even if client-side JavaScript has not loaded or has been blocked by ad blockers.
Implementing the Action Handler (routes/contact.tsx)
Validate incoming FormData with Zod, dispatch the email asynchronously, and return structured JSON responses to the UI.
import type { ActionFunctionArgs } from '@remix-run/node';
import { json } from '@remix-run/node';
import { z } from 'zod';
const ContactSchema = z.object({
email: z.string().email(),
name: z.string().min(2),
message: z.string().min(10),
});
export async function action({ request }: ActionFunctionArgs) {
const formData = await request.formData();
const parsed = ContactSchema.safeParse(Object.fromEntries(formData));
if (!parsed.success) {
return json({ errors: parsed.error.flatten().fieldErrors }, { status: 400 });
}
const { email, name, message } = parsed.data;
const res = await fetch('https://api.sadasend.com/v1/emails', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.SADASEND_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
to: 'support@sadasend.com',
replyTo: email,
subject: `Contact Inquiry from ${name}`,
text: `From: ${name} (${email})\n\nMessage:\n${message}`,
}),
});
if (!res.ok) {
return json({ error: 'Delivery network temporarily unavailable' }, { status: 502 });
}
return json({ success: true });
}Key architectural benefits
- Zero client bundle bloat: Email validation and API credentials remain 100% server-side.
- Built-in CSRF protection: Remix actions handle request origins automatically.
- Instant client revalidation: The UI updates smoothly without full page reloads.
Building AI agents that send email?
Scoped API keys, per-key recipient allowlists, approval mode and a hosted MCP server with ten tools — on the free plan, without a card.