Form Integration

Vue 3 contact form without a backend

A <script setup> component with v-model and one fetch call is all it takes. No Express server and no serverless function, and each submission is emailed to you.

Contact Form for Vue.js

What does the Vue component look like?

A <script setup> single-file component with v-model on each field. Save it as ContactForm.vue, use it in your page and replace FORM_ID. It works in Vite projects and on any static host.

vuejs.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>

    <!-- Response 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>
import { ref, reactive } from 'vue';

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: {
        'Content-Type': 'application/json',
        Accept: 'application/json',
      },
      body: JSON.stringify(form),
    });

    const result = await response.json();
    if (response.ok) {
      statusMessage.value = result.message || 'Message sent successfully!';
      form.email = '';
      form.subject = '';
      form.message = '';
    } else {
      statusMessage.value = result.message || 'Something went wrong';
    }
  } catch (err) {
    statusMessage.value = 'Failed to submit form.';
  } finally {
    loading.value = false;
    setTimeout(() => (statusMessage.value = ''), 4000);
  }
}
</script>
How it works

Getting a Vue form to send

Create the form, paste the endpoint, send a test.

1

Create a form

Sign in and click Create New Form. Free includes 10 forms.

2

Paste the endpoint

Swap FORM_ID in the fetch URL for the ID shown on your Form Setup tab.

3

Send a test

Run your dev server, submit once and check Submissions.

Features

What does Formbold do for a Vue form?

Storage, email, spam checks and integrations. Your component only sends the data.

No server setup

No Express app or function to deploy. The component posts to one URL.

Spam filtering, captcha optional

Basic Spam Filter is a single switch in Settings. This form uses fetch, so Custom reCAPTCHA is the captcha that fits.

File uploads

Starter and higher. v-model can't hold files, so send FormData when you add a file input.

Zapier and Make, too

Starter and higher send entries to Zapier, Make, Slack, Notion or Google Sheets, or to a webhook.

FAQs

Vue questions

Missing fields, Vue 2 and file uploads.

No. The fetch call in the component is all it takes.

Still have a question?

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