formtoDashboard

Astro

Where the code goes

Paste the generated HTML, script included, into a page or component such as src/components/ContactForm.astro. Astro ships the inline script as is, so the form works with zero client framework.

The origin to allow

Allow your site's hostname as an allowed origin, and localhost for astro dev.

Thank-you handling

The script shows the thank-you message in place; without JavaScript, set a success redirect on the form to an Astro page such as /thanks.

File uploads

Add a file field to the definition and regenerate; the form becomes multipart and uploads with the response.

The code

Generated from the form’s fields (plain HTML with a small script). Replace YOUR_FORM_ID with your form’s public id, then restyle it; keep the field names and the hidden _gotcha honeypot.

<form id="formto-form" action="https://api.formto.io/f/YOUR_FORM_ID" method="post" enctype="application/x-www-form-urlencoded">
  <h2>Contact</h2>
  <p>
    <label for="formto-name">Name</label>
    <input type="text" id="formto-name" name="name" required>
  </p>
  <p>
    <label for="formto-email">Email</label>
    <input type="email" id="formto-email" name="email" autocomplete="email" required>
  </p>
  <p>
    <label for="formto-message">Message</label>
    <textarea id="formto-message" name="message" rows="5" required></textarea>
  </p>
  <!-- Spam trap: people never see or fill this field. -->
  <input type="text" name="_gotcha" tabindex="-1" autocomplete="off" aria-hidden="true" style="position:absolute;left:-10000px">
  <button type="submit">Send</button>
  <p data-formto-status role="status" aria-live="polite"></p>
</form>
<script>
  // Progressive enhancement: without JavaScript the form above posts natively.
  ;(function () {
    var form = document.getElementById('formto-form')
    if (!form || !window.fetch || !window.FormData) return
    form.addEventListener('submit', function (event) {
      event.preventDefault()
      var status = form.querySelector('[data-formto-status]')
      var button = form.querySelector('button[type=submit]')
      button.disabled = true
      fetch(form.action, { method: 'POST', body: new FormData(form), headers: { Accept: 'application/json' } })
        .then(function (res) {
          return res.json().then(function (body) {
            if (!res.ok || !body.success) throw new Error(body.error || 'Something went wrong. Please try again.')
            form.reset()
            status.textContent = 'Thanks, we got it.'
          })
        })
        .catch(function (err) {
          status.textContent = err.message || 'Could not send. Please try again.'
        })
        .finally(function () {
          button.disabled = false
        })
    })
  })()
</script>

Other platforms: Plain HTML, React, Next.js, WordPress, Squarespace, Webflow, Wix, Framer, Shopify.