# Bolt.new contact form that sends email (no backend)

> Add a working contact form to a Bolt.new app on Bolt hosting or Netlify. One fetch() call sends through your own SMTP, with a Bolt prompt and the React code.

Source: https://formsmtp.com/guides/bolt-contact-form · Last updated November 2, 2026

## How Bolt handles email

In Bolt, email is sent from **server functions**, which read an email service’s API key from your database’s **Secrets**. Bolt’s email guide lists three prerequisites: a Bolt database, Secrets set up in its settings, and a published project with a custom domain attached. Custom domains are a Pro feature. If you ask for email without naming a provider, Bolt usually picks Resend, and you then verify your domain with Resend’s DNS records.

Hosting matters too. New projects publish to Bolt hosting at a free `.bolt.host` address. You can publish to Netlify instead, but Bolt notes that Netlify can’t host a database or a traditional backend, so the server function route isn’t available there.

| Route | Good | Not so good |
| --- | --- | --- |
| **Server function + email API** | Can email anyone, from your verified domain | Needs a Bolt database, a custom domain (Pro) and DNS setup. Not on Netlify. |
| **FormSMTP form endpoint** | Works on `.bolt.host` and Netlify, sends from the mailbox you already have | Contact forms only email you. To email your users, use the server route below. |

## 1. Create a FormSMTP project

[Sign up free](https://app.formsmtp.com/#/signup) and add a project. Pick your email provider so the SMTP host and port fill in, enter your login, and click *Test connection*. Any mailbox with SMTP access works: [Gmail or Google Workspace](https://formsmtp.com/guides/gmail-smtp-contact-form), [Microsoft 365](https://formsmtp.com/guides/outlook-smtp-contact-form), [Zoho](https://formsmtp.com/guides/zoho-smtp-contact-form), your web host’s mailbox, or a sending service. Personal Outlook.com and Hotmail addresses can’t be used, because Microsoft only lets them sign in with OAuth.

## 2. Lock it to your site

In *Settings → Security*, set **Allowed websites** to every address your app is published at, each written out in full: `https://your-app.bolt.host`, `https://your-site.netlify.app` if you publish there, and your custom domain, and **Allowed recipients** to your own address. Then copy the **form key** from *API & code*. It starts with `fk_`, it only works on the form endpoint, and it can only email you, so it’s safe in your page.

The preview inside the Bolt editor runs on a different address. Test on the published URL, or temporarily add the address shown in the error.

## 3. Paste this prompt into Bolt

Replace `fk_YOUR_FORM_KEY` with your form key:

```text
Add a contact form that emails submissions to me through FormSMTP.

- The form key is fk_YOUR_FORM_KEY. It's a public key made for browser
  code, so it can live in the frontend. Store it as a constant (or a
  VITE_ variable if this is a Vite project).
- Create a ContactForm component with name, email and message fields
  that matches the rest of the site's design.
- On submit, POST JSON to
  https://app.formsmtp.com/api/v1/form/ + the form key
  with the headers Content-Type: application/json and
  Accept: application/json. Include the fields plus
  _subject: "New message from my Bolt app" and
  _t: the time the form first rendered (Date.now()).
- Add a hidden honeypot input named _gotcha (display none, tabIndex -1,
  autoComplete off) and send its value with the rest.
- The response is { success: true } or { success: false, error }.
  Disable the button while sending, show a thank-you message on success
  and the error text on failure.
- Don't add a database, server function or secret for this.
- Put the form on the contact page.
```

## 4. Or paste the component yourself

For a React project (check `package.json`), this is the whole component. On another framework, ask Bolt to port it: the request stays the same.

```jsx
// src/components/ContactForm.jsx
import { useRef, useState } from "react";

// The form key is public: it can only send submissions to you.
const ENDPOINT = "https://app.formsmtp.com/api/v1/form/fk_YOUR_FORM_KEY";

export default function ContactForm() {
  const [status, setStatus] = useState("idle"); // idle | sending | sent | error
  const [error, setError] = useState("");
  const loadedAt = useRef(Date.now());

  async function handleSubmit(e) {
    e.preventDefault();
    const fields = Object.fromEntries(new FormData(e.currentTarget));
    setStatus("sending");
    try {
      const res = await fetch(ENDPOINT, {
        method: "POST",
        headers: { "Content-Type": "application/json", Accept: "application/json" },
        body: JSON.stringify({ ...fields, _subject: "New message from my Bolt app", _t: loadedAt.current }),
      });
      const data = await res.json();
      if (!data.success) throw new Error(data.error);
      setStatus("sent");
    } catch (err) {
      setError(err.message);
      setStatus("error");
    }
  }

  if (status === "sent") return <p>Thanks! We'll be in touch soon.</p>;

  return (
    <form onSubmit={handleSubmit}>
      <input name="name" placeholder="Name" autoComplete="name" required />
      <input name="email" type="email" placeholder="Email" autoComplete="email" required />
      <textarea name="message" placeholder="Message" rows={5} required />
      <input name="_gotcha" style={{ display: "none" }} tabIndex={-1} autoComplete="off" />
      <button disabled={status === "sending"}>{status === "sending" ? "Sending…" : "Send"}</button>
      {status === "error" && <p role="alert">{error}</p>}
    </form>
  );
}
```

## 5. Publish and test

Click **Publish**. To use Netlify instead of Bolt hosting, connect your Netlify account under *All project settings → Applications*, then pick Netlify in *Domains & Hosting → Hosting Provider* before your first publish. Submit the form on the live URL: the message arrives from your own address and appears under *Logs* in FormSMTP.

## Emailing your users from a server function

For emails to other people, like order confirmations, call the send API from a Bolt server function with your secret API key. This needs a Bolt database (for Secrets and server functions) and Bolt hosting, not Netlify.

```text
When an order is placed, email the customer a confirmation through the
FormSMTP API from a server function.

- Read the API key from a secret named FORMSMTP_API_KEY and ask me to
  add it in the database Secrets.
- POST https://app.formsmtp.com/api/v1/send with the header
  Authorization: Bearer FORMSMTP_API_KEY and a JSON body with
  to, subject, html and replyTo.
- Take the recipient and order details from the database, not from
  the request body.
- The response is { success: true, messageId } or
  { success: false, error }. Log the error if it fails.
```

Add the secret yourself under the **database icon → Secrets**; secret names are case-sensitive. Use a separate FormSMTP project for customer email so your contact form project stays locked to your own inbox.

## Troubleshooting

- **“This form isn’t allowed on …”.** Add the exact address from the error. The editor preview, your `.bolt.host` address, your `netlify.app` address and your custom domain are all different origins.
- **It broke after you renamed the Netlify URL.** Update *Allowed websites* to the new `netlify.app` address.
- **“Too many submissions”.** You hit the per-visitor limit while testing: 5 a minute, and 10 an hour by default. Wait, or raise the hourly number in *Settings → Spam protection*.
- **“Recipient not allowed for this project”.** The server function emails customers, but *Allowed recipients* is set to your address. Use a separate project for customer email.

## FAQ

### Do I need a Bolt database to send email?

Not for a contact form. The browser posts straight to FormSMTP. You only need a database, for Secrets and server functions, if your app emails people other than you.

### Does it work on the free plan?

Bolt lets Free and Pro users publish to a `.bolt.host` address, and the form works there. FormSMTP’s free plan includes 1,000 emails a month.

### Does it work on Netlify?

Yes. The form is front-end code that posts to FormSMTP over HTTPS, so it doesn’t need the backend Netlify can’t host. Add your `netlify.app` address to Allowed websites.

### Can the visitor get a confirmation email?

Not from the form endpoint: it only emails you, so a copied form key can’t be used to spam other people. To email the visitor, call the send API with your API key from server code (see the server function section above).

### Is the form key safe in my page?

Yes, it’s made for that. The form key (`fk_`) only works on the form endpoint and always delivers to your own inbox, with per-visitor limits and a spam filter on top. Someone who copies it can’t email anyone else. The API key (`fs_`) can, so keep that one in server code or a secrets store.

## More guides

- [Webflow form to email: custom action with your SMTP](https://formsmtp.com/guides/webflow-contact-form)
- [Framer form to email: webhook or code component](https://formsmtp.com/guides/framer-contact-form)
- [Carrd contact form that emails you from your address](https://formsmtp.com/guides/carrd-contact-form)
- [Lovable contact form that sends email via your SMTP](https://formsmtp.com/guides/lovable-contact-form)
