Frameworks
FormsFort framework guide for HTML, React, React Hook Form, Next.js, Astro, Vue, Svelte, Angular, and Alpine submission patterns.
Frameworks
Use the same endpoint from any frontend stack. Browser submissions are the default protection model. Server-side submissions are supported when the form has a paid/manual sender IP safelist.
Supported frameworks
Plain HTML
Use a normal POST form for no-JavaScript sites.
React
Use fetch with JSON or FormData and render success or error state from the API response.
React Hook Form
Register fields locally, post JSON to the public endpoint, and reset only after a successful API response.
Next.js
Submit from the browser for the public endpoint.
Astro
Use static HTML forms for islands-free pages, or client scripts for progressive success/error rendering.
Vue
Use v-model for fields, then post JSON to the public endpoint from a client-side handler.
Svelte
Bind field state or read FormData in an action handler, then post to the public endpoint from the browser.
Angular
Use reactive forms or template forms and submit JSON from HttpClient with the public access key.
Alpine.js
Use x-data for local submit state and send FormData or JSON from the browser fetch handler.
Plain HTML
<form action="https://api.formsfort.dev/submit" method="POST">
<input type="hidden" name="access_key" value="YOUR_ACCESS_KEY" />
<input name="name" required />
<input name="email" type="email" required />
<textarea name="message" required></textarea>
<button type="submit">Send</button>
</form>React
See the React guide for detailed examples including React Hook Form, file uploads, and captcha tokens.
async function submitForm(fields) {
const response = await fetch("https://api.formsfort.dev/submit", {
method: "POST",
headers: {
accept: "application/json",
"content-type": "application/json",
},
body: JSON.stringify({
access_key: "YOUR_ACCESS_KEY",
...fields,
}),
});
return response.json();
}React Hook Form
Keep the access key in the payload, submit from the browser, and show the API message returned by FormsFort. File fields should use FormData instead of JSON.
import { useState } from "react";
import { useForm } from "react-hook-form";
export function ContactForm() {
const [result, setResult] = useState("");
const {
register,
handleSubmit,
reset,
formState: { errors, isSubmitting },
} = useForm({ mode: "onTouched" });
async function onSubmit(fields) {
setResult("Sending...");
const response = await fetch("https://api.formsfort.dev/submit", {
method: "POST",
headers: {
accept: "application/json",
"content-type": "application/json",
},
body: JSON.stringify({
access_key: "YOUR_ACCESS_KEY",
subject: "New website lead",
from_name: "Example Site",
...fields,
}),
});
const body = await response.json();
setResult(body.message || (response.ok ? "Submitted." : "Submission failed."));
if (response.ok) {
reset();
}
}
return (
<form onSubmit={handleSubmit(onSubmit)}>
<input
{...register("name", { required: "Name is required", maxLength: 80 })}
autoComplete="name"
/>
{errors.name && <p>{errors.name.message}</p>}
<input
type="email"
{...register("email", { required: "Email is required" })}
autoComplete="email"
/>
{errors.email && <p>{errors.email.message}</p>}
<textarea {...register("message", { required: "Message is required" })} />
{errors.message && <p>{errors.message.message}</p>}
<input type="checkbox" {...register("botcheck")} hidden />
<button type="submit" disabled={isSubmitting}>
{isSubmitting ? "Sending..." : "Send"}
</button>
<p role="status">{result}</p>
</form>
);
}Next.js
Next.js server actions and other backend submissions are treated as server-side traffic. They require a paid/manual entitlement and an exact sender IP safelist.
For client-side submissions, use the same React patterns above in a client component.
Astro
Use static HTML forms for content pages, or client scripts when you need inline JSON success and error states.
<form action="https://api.formsfort.dev/submit" method="POST">
<input type="hidden" name="access_key" value="YOUR_ACCESS_KEY" />
<input name="name" required />
<input name="email" type="email" required />
<textarea name="message" required></textarea>
<button type="submit">Send</button>
</form>Vue, Svelte, Angular, Alpine
See the JS Frameworks guide for framework-specific examples.