# Nuxt forms

Add a form to a Nuxt site with a Vue component that submits to Nisuform, without a server route in server/api.

Nuxt renders the form on the server, and the submit runs in the browser straight to your endpoint. You don't need a route in `server/api` or runtime config, because the form key is safe to publish.

<Callout title="Generated for your form">
  The form's **Setup** tab, under **Code**, has this component under **Vue**, ready with your endpoint and field names filled in. **Your design** gives you the styled form from the builder as a component. **Your own styles** gives you a bare component to style your way.
</Callout>

## The component

Put the file in `components/`, so Nuxt imports it for you.

```vue title="components/ContactForm.vue"
<script setup>
const shownAt = Date.now()
const status = ref('idle')

async function onSubmit(event) {
  status.value = 'sending'
  const data = new FormData(event.target)
  data.set('_elapsed', String(Date.now() - shownAt))
  const response = await fetch('https://api.nisuform.com/s/YOUR_FORM_KEY', {
    method: 'POST',
    headers: { Accept: 'application/json' },
    body: data,
  })
  status.value = response.ok ? 'sent' : 'error'
}
</script>

<template>
  <p v-if="status === 'sent'">Thanks! We got your message.</p>
  <form v-else @submit.prevent="onSubmit">
    <input type="email" name="email" placeholder="Email" required />
    <textarea name="message" rows="5" required></textarea>
    <input type="text" name="_gotcha" tabindex="-1" autocomplete="off" style="display: none" />
    <button type="submit" :disabled="status === 'sending'">Send</button>
    <p v-if="status === 'error'" role="alert">Something went wrong. Please try again.</p>
  </form>
</template>
```

## Use it on a page

```vue title="pages/contact.vue"
<template>
  <ContactForm />
</template>
```

## What it does

* Sends `Accept: application/json`, so Nisuform answers with JSON instead of the thank-you page. See [JavaScript and fetch](/docs/connect/javascript).
* Adds `_elapsed`, the time the form was open, and keeps the hidden `_gotcha` honeypot empty. Both feed [spam protection](/docs/protection/spam). See [Special fields](/docs/connect/special-fields).
* Shows a success message when the submission is accepted, and an error when it isn't.
