Formstorkdocs
PricingENTRDashboard

Alpine.js

Alpine.js keeps your markup declarative, so a Formstork form is just an x-on:submit.prevent handler that posts the fields with fetch. No build step, and no backend of your own to run.

Post the form with Alpine

<form
  x-data="{
    sending: false,
    sent: false,
    error: '',
    async send(e) {
      this.sending = true;
      this.error = '';
      const res = await fetch('https://api.formstork.com/submit', {
        method: 'POST',
        body: new FormData(e.target),
        headers: { Accept: 'application/json' },
      });
      const data = await res.json();
      this.sending = false;
      res.ok ? (this.sent = true) : (this.error = data.message);
    }
  }"
  x-on:submit.prevent="send($event)"
>
  <input type="hidden" name="access_key" value="YOUR_ACCESS_KEY" />
  <input type="text" name="name" required />
  <input type="email" name="email" required />
  <textarea name="message" required></textarea>
  <button :disabled="sending" x-text="sending ? 'Sending...' : 'Send'"></button>
  <p x-show="sent">Thanks, your message was sent.</p>
  <p x-show="error" x-text="error"></p>
</form>

The hidden access_key field tells Formstork which form the data belongs to. Adding the Accept: application/json header makes the endpoint reply with JSON instead of redirecting, so you can flip the sent and error state inline.

One line with @formstork/js

If you would rather not hand-write the handler, drop in the SDK and point it at your form:

npm install @formstork/js
import { formstork } from "@formstork/js";

const form = document.querySelector("#contact");
formstork(form, {
  accessKey: "YOUR_ACCESS_KEY",
  onSuccess: () => alert("Thanks, your message was sent."),
  onError: (message) => alert(message),
});

formstork(form, options) collects the fields, posts them, and calls onSuccess or onError for you.

Step by step

  1. Create a free access key in the Formstork dashboard at https://app.formstork.com and paste it in place of YOUR_ACCESS_KEY.
  2. Add Alpine.js to your page the usual way.
  3. Drop in the form markup and set the hidden access_key field to your key.
  4. Wire the x-on:submit.prevent handler to fetch, sending a FormData body with the Accept: application/json header.
  5. Use the sent and error state to show a confirmation or the returned message.
  6. Submit a test message and watch it land in your dashboard. The free plan covers 250 submissions a month.