FormThunder isn't open yet. This site describes the service as it will run at launch. Find out more

FormThunder
Menu

Add a Vue contact form that sends email from a single component

A Vue 3 contact form can send email from a single component. Use script setup with a reactive form object, post it as JSON to FormThunder with fetch, and show the result from a status ref. FormThunder stores each submission and emails your verified address, so you don't run a server for it.

Updated

The Vue code

ContactForm.vue
<script setup>
import { reactive, ref } from "vue";

const form = reactive({ name: "", email: "", message: "", botcheck: false });
const status = ref("idle");

async function submit() {
  status.value = "sending";
  try {
    const response = await fetch("https://formthunder.com/submit", {
      method: "POST",
      headers: { "Content-Type": "application/json", Accept: "application/json" },
      body: JSON.stringify({ ...form, access_key: "YOUR_ACCESS_KEY" }),
    });
    const data = await response.json();
    status.value = data.success ? "sent" : "error";
    if (data.success) Object.assign(form, { name: "", email: "", message: "" });
  } catch {
    status.value = "error";
  }
}
</script>

<template>
  <form @submit.prevent="submit">
    <input v-model="form.botcheck" type="checkbox" style="display: none" tabindex="-1" />
    <label>Name <input v-model="form.name" required /></label>
    <label>Email <input v-model="form.email" type="email" required /></label>
    <label>Message <textarea v-model="form.message" required /></label>
    <button :disabled="status === 'sending'">Send</button>
    <p v-if="status === 'sent'" role="status">Thanks, we got your message.</p>
    <p v-if="status === 'error'" role="alert">That didn't send. Please try again.</p>
  </form>
</template>

Replace YOUR_ACCESS_KEY with your free key. It's public by design, so it's safe in client code.

Notes for Vue

  • botcheck starts as false, and FormThunder treats false and off as an untouched honeypot. Only a truthy value marks the submission as spam.
  • v-model.trim on the email input saves you from pasted trailing spaces, which fail email checks further down the line.
  • With Vite, store the key as VITE_FORMTHUNDER_KEY and read import.meta.env.VITE_FORMTHUNDER_KEY.

Or have your AI add it

Connect the MCP server, then ask. The agent creates the form and writes the code for you, and it can send a real test when it's done.

You, to your AI
Add a FormThunder contact form to this Vue site that emails hello@example.com. Send a test when you're done.

Questions

Does this work with the Options API?

Yes. Put the fields in data() and the fetch in a method. Our Gridsome page has an Options API example.

Can I use axios instead of fetch?

Yes. Post the same object to the same URL. axios sends JSON by default.

Get your Vue form sending

The free plan covers 250 submissions a month, with MCP, the CLI and the brand kit included.