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

FormThunder
Menu

Build a Nuxt contact form with $fetch and no server route

A Nuxt contact form can post to FormThunder with $fetch from the browser, so you don't need a Nitro server route, and nuxt generate works fine. Put the access key in public runtime config, and call $fetch inside the submit handler. Don't use useFetch here: it's meant for loading data during setup, and a form submit isn't that.

Updated

The Nuxt code

nuxt.config.ts
export default defineNuxtConfig({
  runtimeConfig: {
    public: { formthunderKey: "YOUR_ACCESS_KEY" },
  },
});
components/ContactForm.vue
<script setup lang="ts">
const { formthunderKey } = useRuntimeConfig().public;
const form = reactive({ name: "", email: "", message: "" });
const status = ref<"idle" | "sending" | "sent" | "error">("idle");

async function submit() {
  status.value = "sending";
  try {
    await $fetch("https://formthunder.com/submit", {
      method: "POST",
      body: { ...form, access_key: formthunderKey },
    });
    status.value = "sent";
  } catch {
    status.value = "error";
  }
}
</script>

<template>
  <form @submit.prevent="submit">
    <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 Nuxt

  • NUXT_PUBLIC_FORMTHUNDER_KEY overrides the config value at runtime, so you can use a different form per environment without a code change.
  • $fetch sends objects as JSON and throws on a non-2xx reply, so the catch covers both network errors and rejected submissions.
  • If you enable Nuxt's routeRules with CSP headers, allow your FormThunder host under connect-src.

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 Nuxt site that emails hello@example.com. Send a test when you're done.

Questions

Does this work with nuxt generate?

Yes. The request is made from the browser, so a fully static build works.

Why not useFetch?

useFetch runs during setup and caches for SSR. For an action a person triggers, Nuxt's own docs point you to $fetch.

Get your Nuxt form sending

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