Contact Us Form with Astro and Resend
In this article, we will cover how to set up an Astro powered Contact Us form that uses Resend to deliver an email to you when the form is submitted.
Setup Astro
Creating a new Astro application is simple. If you don't have Node.js on your machine, you'll need to download and install it.
Once you have Node on your machine, just run the following command in your terminal.
npm create astro@latest
Once the Astro app is setup, make a new page by creating a new file: src/pages/contact-us.astro
We'll keep it empty for now.
Create Resend Account
Now let's get setup a Resend account and generate an API key.
Once you have the API key, add it to your Astro's .env
file
RESEND_API_KEY=REPLACE_WITH_YOUR_KEY
Create An Astro Action
Now that we have the Astro application created, and a Resend API key to use, let's define an Astro Action. The purpose of this action is to receive the form input, and to send an email to your inbox.
// src/actions/index.ts
import { ActionError, defineAction } from "astro:actions";
import { Resend } from "resend";
import { z } from "astro:schema";
export const server = {
sendEmail: defineAction({
// Set this action to receive data as form submissions
accept: "form",
// Declare what fields to expect, and how to validate them
// Behind the scenes, astro:schema uses ZOD formats
input: z.object({
email: z.string().email().min(1, "Email is required"),
contact_name: z.string().min(1, "Name is required"),
message: z.string().min(1, "Message is required"),
}),
handler: async (
{ email, contact_name, message }
) => {
const resend = new Resend(import.meta.env.RESEND_API_KEY);
const emailPayload = {
from: "onboarding@resend.dev",
to: "YOUR_EMAIL@HERE.com",
subject: `Contact Us Submission from ${contact_name}`,
replyTo: email,
html: `<h1>New Contact Submission</h1><div><p>Email: ${email}</p></div><div><p>Name: ${contact_name}</p></div><div><p>Message: ${message}</p></div>`,
};
const { data, error } = await resend.emails.send(emailPayload);
if (error) {
throw new ActionError({
code: "BAD_REQUEST",
message: error.message,
});
}
return data;
},
}),
};
Build the Contact Page
With the Astro Action in place, let's fill in the empty src/pages/contact-us.astro
page we created earlier.
---
// if you have a layout, import it
import Layout from "../layouts/Layout.astro";
// import the actions
import { actions } from "astro:actions";
// set the page as being client rendered instead of SSR
export const prerender = false;
// Get the result, including any possible errors
const actionResult = Astro.getActionResult(actions.sendEmail);
---
<Layout>
<div>
<h1>Contact Us</h1>
{
actionResult && !actionResult.error && (
<div>
Success!
</div>
)
}
{
actionResult && actionResult.error && (
<div>
Error!
<br />
{actionResult.error.message || "Unknown error"}
</div>
)
}
<!-- default message, when no form is submitted -->
{
!actionResult && (
<p>
Fill out the form below to connect with us.
</p>
)
}
<form action={actions.contact.sendEmail} method="POST">
<div>
<label for="contact_name"> Name: </label>
<input
type="text"
id="name"
name="contact_name"
required
/>
</div>
<div>
<label for="email"> Email: </label>
<input type="email" id="email" name="email" required />
</div>
<div>
<label for="message"> Message: </label>
<textarea id="message" name="message" required></textarea>
</div>
<button type="submit" id="contact-us-submit">
Send Message
</button>
</form>
</div>
</Layout>
All Done!
And there you have it. A fully functional contact-us form. Load up your website and visit the /contact-us
route to see your page in action!
I hope you found this post useful and informative. No go and build something awesome!