Form Integration

Nuxt contact form with nothing in server/api

Skip server/api. A Nuxt component can post straight to your Formbold endpoint with $fetch, and each submission is stored and emailed. It works with nuxi generate static builds too.

Contact Form for Nuxt

The component

A single-file component for components/ContactForm.vue with <script setup>, reactive form state and $fetch. Nuxt auto-imports ref, reactive and $fetch, so there are no import lines. Replace FORM_ID.

nuxtjs.html
<template>
  <form @submit.prevent="submitForm" class="flex flex-col gap-4 max-w-[452px] mx-auto">
    <!-- Email Address -->
    <div class="flex flex-col gap-2">
      <label for="email" class="text-sm font-medium text-gray-700">
        Email Address<span class="ml-0.5 text-red-500">*</span>
      </label>
      <input
        type="email"
        id="email"
        placeholder="Enter your email"
        v-model="form.email"
        required
        class="max-h-11 w-full rounded-xl border border-gray-300 bg-white px-4 py-2.5 text-base text-gray-900 transition-all placeholder:text-[#9ca3af] focus:border-[#5750f1] focus:ring-4 focus:ring-[#5750f1]/10 focus:outline-none"
      />
    </div>

    <!-- Subject -->
    <div class="flex flex-col gap-2">
      <label for="subject" class="text-sm font-medium text-gray-700">
        Subject<span class="ml-0.5 text-red-500">*</span>
      </label>
      <input
        type="text"
        id="subject"
        placeholder="Enter your subject"
        v-model="form.subject"
        required
        class="max-h-11 w-full rounded-xl border border-gray-300 bg-white px-4 py-2.5 text-base text-gray-900 transition-all placeholder:text-[#9ca3af] focus:border-[#5750f1] focus:ring-4 focus:ring-[#5750f1]/10 focus:outline-none"
      />
    </div>

    <!-- Message -->
    <div class="flex flex-col gap-2">
      <label for="message" class="text-sm font-medium text-gray-700">
        Message<span class="ml-0.5 text-red-500">*</span>
      </label>
      <textarea
        id="message"
        rows="5"
        placeholder="Type your message..."
        v-model="form.message"
        required
        class="w-full resize-y rounded-xl border border-gray-300 bg-white px-4 py-3 text-base text-gray-900 transition-all placeholder:text-[#9ca3af] focus:border-[#5750f1] focus:ring-4 focus:ring-[#5750f1]/10 focus:outline-none"
      ></textarea>
    </div>

    <!-- Submit Button -->
    <button
      type="submit"
      :disabled="loading"
      class="flex h-12 w-full cursor-pointer items-center justify-center gap-2 rounded-xl bg-[#111827] px-5 py-3 text-base font-medium text-white shadow-xs transition-all hover:bg-black active:scale-[0.99] disabled:opacity-50"
    >
      {{ loading ? 'Submitting...' : 'Submit Message' }}
    </button>

    <!-- Status Message -->
    <p
      v-if="statusMessage"
      class="rounded-xl p-3 text-center text-sm font-medium bg-gray-50 text-gray-800"
    >
      {{ statusMessage }}
    </p>
  </form>
</template>

<script setup>
const form = reactive({
  email: '',
  subject: '',
  message: '',
});

const loading = ref(false);
const statusMessage = ref('');

async function submitForm() {
  loading.value = true;
  try {
    const response = await $fetch('https://formbold.com/s/FORM_ID', {
      method: 'POST',
      headers: { Accept: 'application/json' },
      body: form,
    });
    statusMessage.value = response.message || 'Message sent successfully!';
    form.email = '';
    form.subject = '';
    form.message = '';
  } catch (err) {
    statusMessage.value = 'Failed to submit form.';
  } finally {
    loading.value = false;
    setTimeout(() => (statusMessage.value = ''), 4000);
  }
}
</script>
How it works

Setting it up in Nuxt

Create the form, paste the endpoint, test it in dev.

1

Create a form

Click Create New Form in Formbold. You can have 10 on Free.

2

Point $fetch at Formbold

Use your https://formbold.com/s/FORM_ID address, from the Form Setup tab, as the $fetch URL.

3

Test with npm run dev

Submit once on localhost:3000 and check Submissions.

Features

What does Formbold handle for a Nuxt app?

The request after submit. Nitro doesn't have to run anything for your form.

No server/api route

Nothing for Nitro to handle, so nuxi generate and static hosting work.

Spam checks for $fetch submits

Turn on Basic Spam Filter. $fetch counts as a script submit, so use Custom reCAPTCHA if you want a captcha.

File uploads

Starter and higher. Send a FormData object as the body when the form has a file input.

Slack, Telegram or Discord

From Starter, the Integrations tab forwards each entry to chat apps, Notion, Google Sheets or a webhook.

FAQs

Nuxt questions

Server routes, static builds and $fetch.

No. The component posts to Formbold directly. Add a server route only if you want to change the data before it's sent.

Still have a question?

The docs cover setup, framework guides, integrations and spam protection, step by step.