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
- Create a free access key in the Formstork dashboard at https://app.formstork.com and paste it in place of
YOUR_ACCESS_KEY. - Add Alpine.js to your page the usual way.
- Drop in the form markup and set the hidden
access_keyfield to your key. - Wire the
x-on:submit.preventhandler tofetch, sending aFormDatabody with theAccept: application/jsonheader. - Use the
sentanderrorstate to show a confirmation or the returned message. - Submit a test message and watch it land in your dashboard. The free plan covers 250 submissions a month.