Back to blog
guides

How to create a Vue.js contact form

Build a Vue.js contact form that collects submissions with no backend. Copy-paste examples for a plain form and a Vue 3 script-setup submission with success and error states.

J
Jesper Christiansen

Vue.js is a popular framework for building web user interfaces. This guide shows you how to add a Vue.js contact form that collects submissions and emails you on every new one — without writing or hosting any backend code. We’ll start with a plain form and then enhance it with Vue 3’s Composition API to submit in the background and show an inline confirmation.

Create your form endpoint in FormBackend

Go create a login and create a new form endpoint in FormBackend. Give it a name you can remember for example: “Vue Contact Form” or something similar for this tutorial. It can always be changed later and is only used for you to remember your form.

Create a new Vue.js app

We’ll start from scratch by creating a new Vue.js app. If you already have one you can skip to the next step. We’re basically following what the Vue.js quickstart guide does.

Go ahead and run the following in your terminal

npm create vue@latest

This will run create-vue which will ask you some questions about how you want to setup your application. It doesn’t really have any impact on how we’re going to do things with FormBackend so pick whatever you’re the most comfortable with.

Go to the new directory of your app, ours is called formbackend-vuejs

cd formbackend-vuejs

Let’s install the dependencies

npm install

and start the local development web server

npm run dev

If you visit the URL it prints (http://localhost:5173) you should see the following:

Visiting the Vue.js development server URL in your browser

Create a contact form endpoint in FormBackend

Log in to your FormBackend account and visit the forms index page. Go ahead and create a new form and give it a name you can remember it by.

After your form has been created, you’ll see the “Submissions” page which is where new submissions will appear. If you navigate to the “Set up” page you can see the unique URL for your form. We’ll copy that!

Add the contact form to your Vue.js app

Now that we have the form endpoint in FormBackend, we can add the form to your Vue.js app. Open up src/App.vue and replace everything with:

We’ll add the following code to it:

<template>
  <main>
    <h1>Contact Form</h1>
    <form action="https://www.formbackend.com/f/{your-identifier}" method="POST">
      <div class="form-fields">
        <label for="name">Name</label>
        <input type="text" id="name" name="name" required>
      </div>

      <div class="form-fields">
        <label for="email">Email</label>
        <input type="email" id="email" name="email" required>
      </div>

      <div class="form-fields">
        <label for="message">Message</label>
        <textarea id="message" name="message" required></textarea>
      </div>

      <button type="submit">Send message</button>
    </form>
  </main>
</template>

<style scoped>
  h1 {
    font-size: 1.8rem;
    font-weight: bold;
    margin-bottom: 1rem;
  }
  .form-fields {
    margin-bottom: 1rem;
  }
  label {
    display: block;
    margin-bottom: 4px;
    font-weight: bold;
    font-size: 0.9rem;
  }
  input[type="text"], input[type="email"], textarea {
    border: 1px solid #ccc;
    font-size: 1rem;
    padding: 6px 10px;
    border-radius: 4px;
  }
  button[type="submit"] {
    background-color: rgb(67 56 202);
    color: white;
    font-size: 0.8rem;
    border: none;
    border-radius: 4px;
    padding: 8px 12px;
    font-weight: 500;
  }
</style>

Notice the action-attribute on the form itself, you need to paste in the unique URL for your form that you copied in the previous step and paste that in here.

This form only has three fields. But you can add as many or as few as you want. As long as they have a unique name attribute which is how we store them in our database and how you can recognize the fields when you view a submission.

If you visit http://localhost:5173 in your browser you should see your form:

The styled Vue.js contact form with name, email, and message fields

After filling it out and hitting the submit button, you’ll be taken to FormBackend’s submission success page. If you navigate to the Submissions tab for the form you created in FormBackend earlier you should see the submission you just added.

Submitting without a page refresh

The form above works on its own, but it redirects to a thank-you page on submit. To keep users on the page and show an inline confirmation, submit it in the background with Vue 3’s Composition API. Replace src/App.vue with:

<script setup>
import { ref } from 'vue'

const status = ref('idle')

async function handleSubmit(event) {
  status.value = 'submitting'

  const form = event.target
  const response = await fetch(form.action, {
    method: 'POST',
    body: new FormData(form),
    headers: { accept: 'application/json' },
  })

  if (response.ok) {
    form.reset()
    status.value = 'success'
  } else {
    status.value = 'error'
  }
}
</script>

<template>
  <main>
    <h1>Contact Form</h1>
    <p v-if="status === 'success'">Thanks! Your message has been sent.</p>
    <form
      v-else
      action="https://www.formbackend.com/f/{your-identifier}"
      method="POST"
      @submit.prevent="handleSubmit"
    >
      <div class="form-fields">
        <label for="name">Name</label>
        <input type="text" id="name" name="name" required>
      </div>

      <div class="form-fields">
        <label for="email">Email</label>
        <input type="email" id="email" name="email" required>
      </div>

      <div class="form-fields">
        <label for="message">Message</label>
        <textarea id="message" name="message" required></textarea>
      </div>

      <button type="submit" :disabled="status === 'submitting'">
        {{ status === 'submitting' ? 'Sending…' : 'Send message' }}
      </button>
      <p v-if="status === 'error'">Something went wrong — please try again.</p>
    </form>
  </main>
</template>

How it works:

  • The @submit.prevent modifier stops the browser’s default full-page submission, so you don’t need to call event.preventDefault() yourself.
  • The browser’s built-in FormData reads every field from the form, so you don’t need a ref per input.
  • The accept: application/json header tells FormBackend to return JSON instead of an HTML page.
  • The status ref drives the UI with v-if/v-else — the form is swapped for a thank-you message once the submission succeeds.

Notifications and integrations

With your Vue.js form collecting submissions, you can:

Guides for other frameworks: Nuxt, React, Next.js, Svelte, Astro, and more.

Add a form backend to your site in minutes

Connect any HTML form to FormBackend and start collecting submissions — no backend code required.

Start free