Use an Astro Action to accept and validate a contact form, then send the message through Resend from server-side code. The handler must run on demand, and your Resend API key must stay out of browser code. This guide uses an Astro Action; an API route is a good alternative when you want an explicit POST endpoint.
Choose how Astro will handle submissions
Resend documents both Astro Actions and API routes for sending email. An Action suits a form-centered workflow: it accepts named form fields, can validate them against a schema, and returns data or an error for the page to handle. An API route gives you a distinct request/response endpoint and more explicit control over request handling.
As an Amazon Associate I earn from qualifying purchases.
Astro Actions are documented from Astro 4.15. Check the current Astro guide and your installed version before using them. Astro’s standard HTML form approach and its API route recipe also run on the server; they are not handled by a static page alone.
Make the handler available at runtime
Configure your Astro deployment for on-demand server execution using an appropriate adapter and deployment settings. The exact setup depends on your hosting platform. Astro’s HTML form recipe lists a server adapter as a prerequisite, and its Action form pattern requires on-demand rendering. A static build without server execution cannot process the submission or call Resend.
#1 Best Overall
- Includes Raspberry Pi 5 with 2.4Ghz 64-bit quad-core CPU (8GB RAM)
- Includes 128GB Micro SD Card pre-loaded with 64-bit Raspberry Pi OS, USB MicroSD Card Reader
- CanaKit Turbine Black Case for the Raspberry Pi 5
- CanaKit Low Noise Bearing System Fan
- Mega Heat Sink - Black Anodized
Configure Resend credentials
Install and configure Resend’s SDK for your project, then add the API key to the server-side environment as RESEND_API_KEY. Resend’s Astro examples initialize the client with import.meta.env.RESEND_API_KEY. Do not put the key in client-side scripts, rendered HTML, or any value exposed to the browser.
You also need a sender address that Resend will accept for your account. Resend’s example uses Acme <[email protected]> as an illustration; it does not establish that address as a production sender for your project. Set the from value to a sender configured for your own use, and choose the intended recipient for contact messages.
Rank #2
- Includes Raspberry Pi 4 4GB Model B with 1.5GHz 64-bit quad-core CPU (4GB RAM)
- Includes Pre-Loaded 32GB EVO+ Micro SD Card (Class 10), USB MicroSD Card Reader
- CanaKit Premium High-Gloss Raspberry Pi 4 Case with Integrated Fan Mount, CanaKit Low Noise Bearing System Fan
- CanaKit 3.5A USB-C Raspberry Pi 4 Power Supply (US Plug) with Noise Filter, Set of Heat Sinks, Display Cable - 6 foot (Supports up to 4K60p)
- CanaKit USB-C PiSwitch (On/Off Power Switch for Raspberry Pi 4)
Build the form and Action
The example below shows the integration shape: an Action accepts form data, validates the named fields, and sends a message. Adapt the imports, file locations, schema, sender and recipient to your Astro project and current Resend SDK. Keep the send operation in server-side code.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
import { defineAction } from 'astro:actions';
import { z } from 'astro:schema';
import { Resend } from 'resend';
const resend = new Resend(import.meta.env.RESEND_API_KEY);
export const server = {
contact: defineAction({
accept: 'form',
input: z.object({
name: z.string().trim().min(1).max(100),
email: z.string().trim().email().max(254),
message: z.string().trim().min(1).max(5000),
}),
handler: async ({ name, email, message }) => {
const result = await resend.emails.send({
from: 'Your configured sender <[email protected]>',
to: '[email protected]',
subject: `Contact form message from ${name}`,
html: `<p>From: ${name} (${email})</p><p>${message}</p>`,
});
if (result.error) {
throw new Error('Message could not be sent. Please try again.');
}
return { sent: true };
},
}),
};
The string values for sender and recipient are examples to replace, not verified production settings. Also escape user-provided values before inserting them into HTML, or use a safe HTML construction method; validation checks shape and length but does not make text safe to interpolate into markup.
Create a form with field names matching the schema. Astro documents submitting a standard HTML form directly to an Action, including a no-client-JavaScript pattern; the exact component syntax and result handling should follow the current Actions guide for your Astro version.
<form method="POST" action={actions.contact}>
<label>
Name
<input name="name" required maxlength="100" />
</label>
<label>
Email
<input name="email" type="email" required maxlength="254" />
</label>
<label>
Message
<textarea name="message" required maxlength="5000"></textarea>
</label>
<button type="submit">Send message</button>
</form>
Validate on the server
The browser’s required, type and maxlength checks help visitors catch mistakes, but they are not a security boundary. Requests can bypass browser validation, so enforce required fields, formats and sensible length limits in the server-side schema before using any submitted value in an email subject, recipient, or body.
Rank #4
- Broadcom BCM2711, quad-core Cortex-A72 (ARM v8) 64-bit SoC @ 1. 5GHz
- 2. 4 GHz and 5. 0 GHz IEEE 802. 11b/g/n/ac wireless LAN, Bluetooth 5. 0, BLE
- 2 × USB 3. 0 ports, 2 x USB 2. 0 Ports
- 2 × micro HDMI ports supproting up to 4Kp60 video resolution
- Micro SD card slot for loading operating system and data storage
Show submission success and failure
An Action returns data when it succeeds and an error when validation or sending fails. Use that result in the page to show a clear confirmation only after the send succeeds, and a useful error when it does not. Astro’s guide also documents redirecting after success. Avoid displaying raw exception details to visitors; keep diagnostic information in server-side logs.
When to use an API route instead
Choose an API route if you want a dedicated POST URL or need to manage the HTTP request and response explicitly. Astro’s recipe receives the submission at a POST endpoint, reads the form data, and advises validating values before using them. The route still needs on-demand server execution, server-side credentials and clear success and error responses; changing the entry point does not remove those requirements.
Quick Recap
Best Value
- Includes Raspberry Pi 5 16GB with 2.4Ghz 64-bit quad-core CPU (16GB RAM)
- Includes 128GB Micro SD Card pre-loaded with 64-bit Raspberry Pi OS, USB MicroSD Card Reader
- CanaKit Turbine Black Case for the Raspberry Pi 5
- CanaKit Low Noise Bearing System Fan
- Mega Heat Sink - Black Anodized
Official implementation references
- Resend: Send emails with Astro — examples of both an API route and an Astro Action.
- Astro: Actions — form acceptance, input validation and handling Action results.
- Astro: Build HTML forms in Astro pages — server-side form handling and adapter prerequisite.
- Astro: Build forms with API routes — POST endpoint and form-data handling.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




